개인정보 관련 업데이트 진행

ot 정보는 타인이 못봄
휴가신청 관련건도 타인이 못봄
This commit is contained in:
backuppc
2025-11-11 11:43:29 +09:00
parent e6a39d52e9
commit 709ca7c85a
57 changed files with 1869 additions and 8491 deletions

View File

@@ -50,7 +50,7 @@
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>Full</DebugType> <DebugType>Full</DebugType>
<Optimize>False</Optimize> <Optimize>False</Optimize>
<OutputPath>..\..\..\..\amkor\GroupWare\</OutputPath> <OutputPath>..\..\..\..\Amkor\GroupWare\</OutputPath>
<DefineConstants>TRACE;DEBUG;WEB1</DefineConstants> <DefineConstants>TRACE;DEBUG;WEB1</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
@@ -671,21 +671,6 @@
<Content Include="Web\wwwroot\Project\index.html"> <Content Include="Web\wwwroot\Project\index.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<None Include="Web\wwwroot\react\LoginApp.jsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Web\wwwroot\react\TestApp.jsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Web\wwwroot\react\DashboardApp.jsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Web\wwwroot\react\CommonNavigation.jsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Web\wwwroot\react\CommonCode.jsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Web\wwwroot\css\common.css"> <None Include="Web\wwwroot\css\common.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
@@ -722,18 +707,6 @@
<None Include="Web\wwwroot\login.html"> <None Include="Web\wwwroot\login.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="Web\wwwroot\react\JobReport.jsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Web\wwwroot\react\Kuntae.jsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Web\wwwroot\react\Todo.jsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Web\wwwroot\react\Project.jsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Web\wwwroot\lib\js\react.development.js"> <None Include="Web\wwwroot\lib\js\react.development.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
@@ -749,9 +722,6 @@
<None Include="Web\wwwroot\lib\js\tailwind-config.js"> <None Include="Web\wwwroot\lib\js\tailwind-config.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="Web\wwwroot\react\DevWarning.jsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0"> <BootstrapperPackage Include=".NETFramework,Version=v4.0">

View File

@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호가 자동으로 // 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호가 자동으로
// 지정되도록 할 수 있습니다. // 지정되도록 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("25.11.03.1350")] [assembly: AssemblyVersion("25.11.11.1030")]
[assembly: AssemblyFileVersion("25.11.03.1350")] [assembly: AssemblyFileVersion("25.11.11.1030")]

View File

@@ -18,7 +18,34 @@ namespace Project.OWIN
{ {
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
// 정적 파일 서빙을 가장 먼저 설정 (다른 모든 미들웨어보다 우선) // 캐시 방지 미들웨어를 가장 먼저 설정 (정적 파일 서빙보다 우선)
app.Use(async (context, next) =>
{
var path = context.Request.Path.Value;
// 모든 정적 리소스에 대해 캐시 방지 헤더 설정
if (path.EndsWith(".js") ||
path.EndsWith(".css") ||
path.EndsWith(".jsx") ||
path.EndsWith(".tsx") ||
path.EndsWith(".html") ||
path.EndsWith(".htm"))
{
context.Response.Headers["Cache-Control"] = "no-cache, no-store, must-revalidate";
context.Response.Headers["Pragma"] = "no-cache";
context.Response.Headers["Expires"] = "0";
}
// JSX/TSX 파일을 JavaScript로 처리
if (path.EndsWith(".jsx") || path.EndsWith(".tsx"))
{
context.Response.ContentType = "application/javascript; charset=utf-8";
}
await next();
});
// 정적 파일 서빙 설정
var staticFileOptions = new FileServerOptions var staticFileOptions = new FileServerOptions
{ {
EnableDefaultFiles = true, EnableDefaultFiles = true,
@@ -28,31 +55,6 @@ namespace Project.OWIN
}; };
app.UseFileServer(staticFileOptions); app.UseFileServer(staticFileOptions);
// 캐시 방지 미들웨어 (정적 파일이 처리되지 않은 경우에만 적용)
app.Use(async (context, next) =>
{
var path = context.Request.Path.Value;
if (path.EndsWith(".js") ||
path.EndsWith(".css") ||
path.EndsWith(".jsx") ||
path.EndsWith(".tsx") ||
path.EndsWith(".html"))
{
context.Response.Headers["Cache-Control"] = "no-cache, no-store, must-revalidate";
context.Response.Headers["Pragma"] = "no-cache";
context.Response.Headers["Expires"] = "0";
}
// JSX/TSX 파일을 JavaScript로 처리
if (path.EndsWith(".jsx") || path.EndsWith(".tsx"))
{
context.Response.ContentType = "application/javascript";
}
await next();
});
// Configure Web API for Self-Host (정적 파일 후에 설정) // Configure Web API for Self-Host (정적 파일 후에 설정)
HttpConfiguration config = new HttpConfiguration(); HttpConfiguration config = new HttpConfiguration();

View File

@@ -7,7 +7,7 @@
<meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0"> <meta http-equiv="Expires" content="0">
<meta name="version" content="v2.0-20250127"> <meta name="version" content="v2.0-20250127">
<title>근태현황 대시보드</title> <title>근태현황 대시보드*</title>
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<script> <script>
tailwind.config = { tailwind.config = {
@@ -218,105 +218,6 @@
</div> </div>
</div> </div>
<!-- 출근 대상자 모달 -->
<div id="presentUserModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="glass-effect rounded-2xl w-full max-w-4xl max-h-[80vh] overflow-hidden animate-slide-up">
<!-- 모달 헤더 -->
<div class="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 class="text-xl font-semibold text-white flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
금일 출근 대상자 목록
</h2>
<button onclick="hidePresentUserModal()" class="text-white/70 hover:text-white transition-colors">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<!-- 모달 내용 -->
<div class="overflow-x-auto max-h-[60vh] custom-scrollbar">
<table class="w-full">
<thead class="bg-white/10 sticky top-0">
<tr>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">사번</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">이름</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">공정</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">직급</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">상태</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">이메일</th>
</tr>
</thead>
<tbody id="presentUserTable" class="divide-y divide-white/10">
<!-- 데이터가 여기에 표시됩니다 -->
</tbody>
</table>
</div>
<!-- 모달 푸터 -->
<div class="px-6 py-4 border-t border-white/10 flex justify-between items-center">
<p class="text-white/70 text-sm"><span id="presentUserCount">0</span></p>
<button onclick="hidePresentUserModal()" class="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors">
닫기
</button>
</div>
</div>
</div>
</div>
<!-- 휴가요청 모달 -->
<div id="holidayRequestModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden z-50">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="glass-effect rounded-2xl w-full max-w-6xl max-h-[80vh] overflow-hidden animate-slide-up">
<!-- 모달 헤더 -->
<div class="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 class="text-xl font-semibold text-white flex items-center">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
휴가 신청 목록
</h2>
<button onclick="hideHolidayRequestModal()" class="text-white/70 hover:text-white transition-colors">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<!-- 모달 내용 -->
<div class="overflow-x-auto max-h-[60vh] custom-scrollbar">
<table class="w-full">
<thead class="bg-white/10 sticky top-0">
<tr>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">사번</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">이름</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">항목</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">일자</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">요청일</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">요청시간</th>
<th class="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">비고</th>
</tr>
</thead>
<tbody id="holidayRequestTable" class="divide-y divide-white/10">
<!-- 데이터가 여기에 표시됩니다 -->
</tbody>
</table>
</div>
<!-- 모달 푸터 -->
<div class="px-6 py-4 border-t border-white/10 flex justify-between items-center">
<p class="text-white/70 text-sm"><span id="holidayRequestCount">0</span></p>
<button onclick="hideHolidayRequestModal()" class="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors">
닫기
</button>
</div>
</div>
</div>
</div>
<!-- 구매NR 모달 --> <!-- 구매NR 모달 -->
<div id="purchaseNRModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden z-50"> <div id="purchaseNRModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden z-50">
<div class="flex items-center justify-center min-h-screen p-4"> <div class="flex items-center justify-center min-h-screen p-4">

View File

@@ -1,559 +0,0 @@
// CommonApp.jsx - React Common Code Management Component for GroupWare
const { useState, useEffect, useRef } = React;
const CommonApp = () => {
// 상태 관리
const [groupData, setGroupData] = useState([]);
const [currentData, setCurrentData] = useState([]);
const [selectedGroupCode, setSelectedGroupCode] = useState(null);
const [selectedGroupName, setSelectedGroupName] = useState('');
const [loading, setLoading] = useState(false);
const [showEditModal, setShowEditModal] = useState(false);
const [showDeleteModal, setShowDeleteModal] = useState(false);
const [deleteTargetIdx, setDeleteTargetIdx] = useState(null);
const [editMode, setEditMode] = useState('add');
// 편집 폼 데이터
const [editData, setEditData] = useState({
idx: '',
grp: '',
code: '',
svalue: '',
ivalue: '',
fvalue: '',
svalue2: '',
memo: ''
});
// 페이지 로드시 초기 데이터 로드
useEffect(() => {
loadGroups();
}, []);
// API 호출 함수들
const loadGroups = async () => {
setLoading(true);
try {
const response = await fetch('http://127.0.0.1:7979/Common/GetGroups');
const data = await response.json();
setGroupData(data || []);
} catch (error) {
console.error('그룹 데이터 로드 중 오류 발생:', error);
showNotification('그룹 데이터 로드 중 오류가 발생했습니다.', 'error');
} finally {
setLoading(false);
}
};
const loadDataByGroup = async (grp) => {
setLoading(true);
try {
let url = 'http://127.0.0.1:7979/Common/GetList';
if (grp) {
url += '?grp=' + encodeURIComponent(grp);
}
const response = await fetch(url);
const data = await response.json();
setCurrentData(data || []);
} catch (error) {
console.error('데이터 로드 중 오류 발생:', error);
showNotification('데이터 로드 중 오류가 발생했습니다.', 'error');
} finally {
setLoading(false);
}
};
const saveData = async () => {
try {
const data = {
idx: parseInt(editData.idx) || 0,
grp: editData.grp,
code: editData.code,
svalue: editData.svalue,
ivalue: parseInt(editData.ivalue) || 0,
fvalue: parseFloat(editData.fvalue) || 0.0,
svalue2: editData.svalue2,
memo: editData.memo
};
setLoading(true);
const response = await fetch('http://127.0.0.1:7979/Common/Save', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
const result = await response.json();
if (result.Success) {
showNotification(result.Message, 'success');
setShowEditModal(false);
if (selectedGroupCode) {
loadDataByGroup(selectedGroupCode);
}
} else {
showNotification(result.Message, 'error');
}
} catch (error) {
console.error('저장 중 오류 발생:', error);
showNotification('저장 중 오류가 발생했습니다.', 'error');
} finally {
setLoading(false);
}
};
const deleteItem = async () => {
if (!deleteTargetIdx) return;
try {
setLoading(true);
const response = await fetch('http://127.0.0.1:7979/Common/Delete', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ idx: deleteTargetIdx })
});
const data = await response.json();
if (data.Success) {
showNotification(data.Message, 'success');
setShowDeleteModal(false);
if (selectedGroupCode) {
loadDataByGroup(selectedGroupCode);
}
} else {
showNotification(data.Message, 'error');
}
} catch (error) {
console.error('삭제 중 오류 발생:', error);
showNotification('삭제 중 오류가 발생했습니다.', 'error');
} finally {
setLoading(false);
setDeleteTargetIdx(null);
}
};
// 이벤트 핸들러들
const selectGroup = (code, name) => {
setSelectedGroupCode(code);
setSelectedGroupName(name);
loadDataByGroup(code);
};
const openAddModal = () => {
if (!selectedGroupCode) {
showNotification('먼저 코드그룹을 선택하세요.', 'warning');
return;
}
setEditMode('add');
setEditData({
idx: '',
grp: selectedGroupCode,
code: '',
svalue: '',
ivalue: '',
fvalue: '',
svalue2: '',
memo: ''
});
setShowEditModal(true);
};
const openEditModal = (item) => {
setEditMode('edit');
setEditData({
idx: item.idx,
grp: item.grp || '',
code: item.code || '',
svalue: item.svalue || '',
ivalue: item.ivalue || '',
fvalue: item.fvalue || '',
svalue2: item.svalue2 || '',
memo: item.memo || ''
});
setShowEditModal(true);
};
const openDeleteModal = (idx) => {
setDeleteTargetIdx(idx);
setShowDeleteModal(true);
setShowEditModal(false);
};
const closeModals = () => {
setShowEditModal(false);
setShowDeleteModal(false);
setDeleteTargetIdx(null);
};
const handleInputChange = (field, value) => {
setEditData(prev => ({ ...prev, [field]: value }));
};
const showNotification = (message, type = 'info') => {
// 기존 알림 제거
const existing = document.querySelectorAll('.notification-toast');
existing.forEach(el => el.remove());
const colors = {
info: 'bg-blue-500/90',
success: 'bg-green-500/90',
warning: 'bg-yellow-500/90',
error: 'bg-red-500/90'
};
const icons = {
info: '🔵',
success: '✅',
warning: '⚠️',
error: '❌'
};
const notification = document.createElement('div');
notification.className = `notification-toast fixed top-4 right-4 ${colors[type]} backdrop-blur-sm text-white px-4 py-3 rounded-lg z-50 shadow-lg border border-white/20`;
notification.innerHTML = `<div class="flex items-center"><span class="mr-2">${icons[type]}</span>${message}</div>`;
document.body.appendChild(notification);
setTimeout(() => {
notification.style.transform = 'translateX(100%)';
notification.style.opacity = '0';
setTimeout(() => notification.remove(), 300);
}, 3000);
};
// 키보드 이벤트
useEffect(() => {
const handleKeyDown = (e) => {
if (e.key === 'Escape') {
closeModals();
}
};
document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}, []);
return (
<div className="bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 min-h-screen text-white">
{/* Navigation Component */}
<CommonNavigation currentPage="common" />
<div className="container mx-auto px-4 py-8">
{/* 2열 구조 메인 컨테이너 */}
<div className="flex gap-6 h-[calc(100vh-200px)]">
{/* 좌측: 코드그룹 리스트 */}
<div className="w-80">
<div className="glass-effect rounded-2xl h-full card-hover animate-slide-up flex flex-col">
<div className="p-4 border-b border-white/10">
<h3 className="text-lg font-semibold text-white flex items-center">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 11H5m14-7l-7 7-7-7M19 21l-7-7-7 7"></path>
</svg>
코드그룹 목록
</h3>
</div>
<div className="flex-1 overflow-y-auto custom-scrollbar p-2">
<div className="space-y-1">
{groupData.length === 0 ? (
<div className="text-white/70 text-center py-4">그룹 데이터가 없습니다.</div>
) : (
groupData.map(group => (
<div
key={group.code}
className={`cursor-pointer p-3 rounded-lg border border-white/20 hover:bg-white/10 transition-all ${
selectedGroupCode === group.code ? 'bg-white/20' : ''
}`}
onClick={() => selectGroup(group.code, group.memo)}
>
<div className="flex items-center">
<div className="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center mr-3">
<span className="text-white text-sm font-medium">{group.code}</span>
</div>
<div className="flex-1">
<div className="text-white font-medium">{group.memo}</div>
</div>
</div>
</div>
))
)}
</div>
</div>
</div>
</div>
{/* 우측: 상세 데이터 */}
<div className="flex-1">
<div className="glass-effect rounded-2xl h-full card-hover animate-slide-up flex flex-col">
{/* 상단 헤더 */}
<div className="p-4 border-b border-white/10 flex items-center justify-between">
<div>
<h3 className="text-lg font-semibold text-white flex items-center">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
<span>
{selectedGroupCode ? `${selectedGroupCode} - ${selectedGroupName}` : '코드그룹을 선택하세요'}
</span>
</h3>
<p className="text-white/70 text-sm mt-1">
<span className="text-white font-medium">{currentData.length}</span>
</p>
</div>
<button
onClick={openAddModal}
className="bg-white/20 hover:bg-white/30 backdrop-blur-sm text-white px-4 py-2 rounded-lg transition-all border border-white/30 flex items-center text-sm"
>
<svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
</svg>
추가
</button>
</div>
{/* 데이터 테이블 */}
<div className="flex-1 overflow-x-auto overflow-y-auto custom-scrollbar">
<table className="w-full">
<thead className="bg-white/10 sticky top-0">
<tr>
<th className="w-24 px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">코드</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">비고</th>
<th className="w-32 px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">(문자열)</th>
<th className="w-20 px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">(숫자)</th>
<th className="w-20 px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">(실수)</th>
<th className="w-24 px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">값2</th>
</tr>
</thead>
<tbody className="divide-y divide-white/10">
{currentData.length === 0 ? (
<tr>
<td colSpan="6" className="px-4 py-8 text-center text-white/70">
<svg className="w-12 h-12 mx-auto mb-2 text-white/30" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
{selectedGroupCode ? '데이터가 없습니다.' : '좌측에서 코드그룹을 선택하세요'}
</td>
</tr>
) : (
currentData.map(item => (
<tr
key={item.idx}
className="hover:bg-white/5 transition-colors cursor-pointer"
onClick={() => openEditModal(item)}
>
<td className="px-4 py-4 whitespace-nowrap text-sm text-white">{item.code || '-'}</td>
<td className="px-4 py-4 text-sm text-white">{item.memo || '-'}</td>
<td className="px-4 py-4 text-sm text-white max-w-32 truncate" title={item.svalue || '-'}>
{item.svalue || '-'}
</td>
<td className="px-4 py-4 whitespace-nowrap text-sm text-white">{item.ivalue || '0'}</td>
<td className="px-4 py-4 whitespace-nowrap text-sm text-white">{item.fvalue || '0.0'}</td>
<td className="px-4 py-4 whitespace-nowrap text-sm text-white">{item.svalue2 || '-'}</td>
</tr>
))
)}
</tbody>
</table>
</div>
</div>
</div>
</div>
{/* 로딩 인디케이터 */}
{loading && (
<div className="fixed top-4 right-4 bg-white/20 backdrop-blur-sm rounded-full px-4 py-2 text-white text-sm z-40">
<div className="flex items-center">
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
데이터 로딩 ...
</div>
</div>
)}
</div>
{/* 추가/편집 모달 */}
{showEditModal && (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50">
<div className="flex items-center justify-center min-h-screen p-4">
<div className="glass-effect rounded-2xl w-full max-w-2xl animate-slide-up">
{/* 모달 헤더 */}
<div className="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 className="text-xl font-semibold text-white">
{editMode === 'add' ? '공용코드 추가' : '공용코드 편집'}
</h2>
<button
onClick={closeModals}
className="text-white/70 hover:text-white transition-colors"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
{/* 모달 내용 */}
<div className="p-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-white/70 mb-2">코드그룹 *</label>
<select
value={editData.grp}
onChange={(e) => handleInputChange('grp', e.target.value)}
required
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
>
<option value="" className="bg-gray-800 text-white">선택하세요</option>
{groupData.map(group => (
<option key={group.code} value={group.code} className="bg-gray-800 text-white">
{group.code}-{group.memo}
</option>
))}
</select>
</div>
<div>
<label className="block text-sm font-medium text-white/70 mb-2">코드 *</label>
<input
type="text"
value={editData.code}
onChange={(e) => handleInputChange('code', e.target.value)}
required
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="코드를 입력하세요"
/>
</div>
<div>
<label className="block text-sm font-medium text-white/70 mb-2">(문자열)</label>
<input
type="text"
value={editData.svalue}
onChange={(e) => handleInputChange('svalue', e.target.value)}
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="문자열 값"
/>
</div>
<div>
<label className="block text-sm font-medium text-white/70 mb-2">(숫자)</label>
<input
type="number"
value={editData.ivalue}
onChange={(e) => handleInputChange('ivalue', e.target.value)}
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="숫자 값"
/>
</div>
<div>
<label className="block text-sm font-medium text-white/70 mb-2">(실수)</label>
<input
type="number"
step="0.01"
value={editData.fvalue}
onChange={(e) => handleInputChange('fvalue', e.target.value)}
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="실수 값"
/>
</div>
<div>
<label className="block text-sm font-medium text-white/70 mb-2">값2</label>
<input
type="text"
value={editData.svalue2}
onChange={(e) => handleInputChange('svalue2', e.target.value)}
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="추가 문자열 값"
/>
</div>
</div>
<div className="mt-4">
<label className="block text-sm font-medium text-white/70 mb-2">비고</label>
<textarea
value={editData.memo}
onChange={(e) => handleInputChange('memo', e.target.value)}
rows="3"
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="비고사항을 입력하세요"
></textarea>
</div>
</div>
{/* 모달 푸터 */}
<div className="px-6 py-4 border-t border-white/10 flex justify-between">
{editMode === 'edit' && (
<button
onClick={() => openDeleteModal(editData.idx)}
className="bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-lg transition-colors flex items-center"
>
<svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
</svg>
삭제
</button>
)}
<div className="flex gap-2 ml-auto">
<button
onClick={closeModals}
className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors"
>
취소
</button>
<button
onClick={saveData}
className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors"
>
저장
</button>
</div>
</div>
</div>
</div>
</div>
)}
{/* 삭제 확인 모달 */}
{showDeleteModal && (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50">
<div className="flex items-center justify-center min-h-screen p-4">
<div className="glass-effect rounded-2xl w-full max-w-md animate-slide-up">
<div className="p-6">
<div className="flex items-center mb-4">
<div className="w-12 h-12 bg-red-100/20 rounded-full flex items-center justify-center mr-4">
<svg className="w-6 h-6 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.268 18.5c-.77.833.192 2.5 1.732 2.5z"></path>
</svg>
</div>
<div>
<h3 className="text-lg font-medium text-white">삭제 확인</h3>
<p className="text-sm text-white/70"> 작업은 되돌릴 없습니다.</p>
</div>
</div>
<p className="text-white/80 mb-6">
선택한 공용코드를 삭제하시겠습니까?<br/>
<span className="text-sm text-white/60"> 작업은 되돌릴 없습니다.</span>
</p>
<div className="flex justify-end gap-2">
<button
onClick={closeModals}
className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors"
>
취소
</button>
<button
onClick={deleteItem}
className="bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-lg transition-colors"
>
삭제
</button>
</div>
</div>
</div>
</div>
</div>
)}
</div>
);
};

View File

@@ -1,590 +0,0 @@
const { useState, useEffect } = React;
function CommonCode() {
// 상태 관리
const [currentData, setCurrentData] = useState([]);
const [groupData, setGroupData] = useState([]);
const [selectedGroupCode, setSelectedGroupCode] = useState(null);
const [selectedGroupName, setSelectedGroupName] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [showEditModal, setShowEditModal] = useState(false);
const [showDeleteModal, setShowDeleteModal] = useState(false);
const [deleteTargetIdx, setDeleteTargetIdx] = useState(null);
const [editData, setEditData] = useState({
idx: '',
grp: '',
code: '',
svalue: '',
ivalue: '',
fvalue: '',
svalue2: '',
memo: ''
});
const [isEditMode, setIsEditMode] = useState(false);
// 컴포넌트 마운트 시 초기 데이터 로드
useEffect(() => {
loadGroups();
}, []);
// 코드그룹 목록 로드
const loadGroups = async () => {
setIsLoading(true);
try {
const response = await fetch('/Common/GetGroups');
const data = await response.json();
setGroupData(data || []);
} catch (error) {
console.error('그룹 데이터 로드 중 오류 발생:', error);
showNotification('그룹 데이터 로드 중 오류가 발생했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 그룹 선택 처리
const selectGroup = async (code, name) => {
setSelectedGroupCode(code);
setSelectedGroupName(name);
await loadDataByGroup(code);
};
// 특정 그룹의 데이터 로드
const loadDataByGroup = async (grp) => {
setIsLoading(true);
try {
let url = '/Common/GetList';
if (grp) {
url += '?grp=' + encodeURIComponent(grp);
}
const response = await fetch(url);
const data = await response.json();
setCurrentData(data || []);
} catch (error) {
console.error('데이터 로드 중 오류 발생:', error);
showNotification('데이터 로드 중 오류가 발생했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 추가 모달 표시
const showAddModal = () => {
if (!selectedGroupCode) {
showNotification('먼저 코드그룹을 선택하세요.', 'warning');
return;
}
setIsEditMode(false);
setEditData({
idx: '',
grp: selectedGroupCode,
code: '',
svalue: '',
ivalue: '',
fvalue: '',
svalue2: '',
memo: ''
});
setShowEditModal(true);
};
// 편집 모달 표시
const editItem = (idx) => {
const item = currentData.find(x => x.idx === idx);
if (!item) return;
setIsEditMode(true);
setEditData({
idx: item.idx,
grp: item.grp || '',
code: item.code || '',
svalue: item.svalue || '',
ivalue: item.ivalue || '',
fvalue: item.fvalue || '',
svalue2: item.svalue2 || '',
memo: item.memo || ''
});
setShowEditModal(true);
};
// 데이터 저장
const saveData = async () => {
const form = document.getElementById('editForm');
if (!form.checkValidity()) {
form.reportValidity();
return;
}
const data = {
idx: parseInt(editData.idx) || 0,
grp: editData.grp,
code: editData.code,
svalue: editData.svalue,
ivalue: parseInt(editData.ivalue) || 0,
fvalue: parseFloat(editData.fvalue) || 0.0,
svalue2: editData.svalue2,
memo: editData.memo
};
setIsLoading(true);
try {
const response = await fetch('/Common/Save', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
const result = await response.json();
if (result.Success) {
showNotification(result.Message, 'success');
setShowEditModal(false);
if (selectedGroupCode) {
await loadDataByGroup(selectedGroupCode);
}
} else {
showNotification(result.Message, 'error');
}
} catch (error) {
console.error('저장 중 오류 발생:', error);
showNotification('저장 중 오류가 발생했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 삭제 확인
const confirmDelete = async () => {
if (!deleteTargetIdx) return;
setIsLoading(true);
try {
const response = await fetch('/Common/Delete', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ idx: deleteTargetIdx })
});
const data = await response.json();
if (data.Success) {
showNotification(data.Message, 'success');
setShowDeleteModal(false);
setDeleteTargetIdx(null);
if (selectedGroupCode) {
await loadDataByGroup(selectedGroupCode);
}
} else {
showNotification(data.Message, 'error');
}
} catch (error) {
console.error('삭제 중 오류 발생:', error);
showNotification('삭제 중 오류가 발생했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 삭제 요청
const deleteCurrentItem = () => {
if (!editData.idx) {
showNotification('삭제할 항목이 없습니다.', 'warning');
return;
}
setDeleteTargetIdx(parseInt(editData.idx));
setShowEditModal(false);
setShowDeleteModal(true);
};
// 알림 표시 함수
const showNotification = (message, type = 'info') => {
const colors = {
info: 'bg-blue-500/90 backdrop-blur-sm',
success: 'bg-green-500/90 backdrop-blur-sm',
warning: 'bg-yellow-500/90 backdrop-blur-sm',
error: 'bg-red-500/90 backdrop-blur-sm'
};
const icons = {
info: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
),
success: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
),
warning: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.268 18.5c-.77.833.192 2.5 1.732 2.5z"></path>
</svg>
),
error: (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
)
};
// React에서는 실제 DOM 조작 대신 Toast 라이브러리나 상태로 관리하는 것이 좋습니다
// 여기서는 기존 방식을 유지하되 React 컴포넌트 스타일로 구현
const notification = document.createElement('div');
notification.className = `fixed top-4 right-4 ${colors[type]} text-white px-4 py-3 rounded-lg z-50 transition-all duration-300 transform translate-x-0 opacity-100 shadow-lg border border-white/20`;
notification.innerHTML = `
<div class="flex items-center">
${type === 'info' ? '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>' : ''}
${type === 'success' ? '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>' : ''}
${type === 'warning' ? '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.268 18.5c-.77.833.192 2.5 1.732 2.5z"></path></svg>' : ''}
${type === 'error' ? '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>' : ''}
<span class="ml-2">${message}</span>
</div>
`;
notification.style.transform = 'translateX(100%)';
notification.style.opacity = '0';
document.body.appendChild(notification);
setTimeout(() => {
notification.style.transform = 'translateX(0)';
notification.style.opacity = '1';
}, 10);
setTimeout(() => {
notification.style.transform = 'translateX(100%)';
notification.style.opacity = '0';
setTimeout(() => notification.remove(), 300);
}, 3000);
};
// 키보드 이벤트 핸들러
useEffect(() => {
const handleKeyDown = (e) => {
if (e.key === 'Escape') {
setShowEditModal(false);
setShowDeleteModal(false);
}
};
document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}, []);
// 입력 필드 변경 핸들러
const handleInputChange = (field, value) => {
setEditData(prev => ({ ...prev, [field]: value }));
};
return (
<div className="container mx-auto px-4 py-8">
{/* 2열 구조 메인 컨테이너 */}
<div className="flex gap-6 h-[calc(100vh-200px)]">
{/* 좌측: 코드그룹 리스트 */}
<div className="w-80">
<div className="glass-effect rounded-2xl h-full card-hover animate-slide-up flex flex-col">
<div className="p-4 border-b border-white/10">
<h3 className="text-lg font-semibold text-white flex items-center">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 11H5m14-7l-7 7-7-7M19 21l-7-7-7 7"></path>
</svg>
코드그룹 목록
</h3>
</div>
<div className="flex-1 overflow-y-auto custom-scrollbar p-2">
<div className="space-y-1">
{groupData.length === 0 ? (
<div className="text-white/70 text-center py-4">그룹 데이터가 없습니다.</div>
) : (
groupData.map(group => (
<div
key={group.code}
className={`group-item cursor-pointer p-3 rounded-lg border border-white/20 hover:bg-white/10 transition-all ${
selectedGroupCode === group.code ? 'bg-white/20' : ''
}`}
onClick={() => selectGroup(group.code, group.memo)}
>
<div className="flex items-center">
<div className="w-8 h-8 bg-white/20 rounded-full flex items-center justify-center mr-3">
<span className="text-white text-sm font-medium">{group.code}</span>
</div>
<div className="flex-1">
<div className="text-white font-medium">{group.memo}</div>
</div>
</div>
</div>
))
)}
</div>
</div>
</div>
</div>
{/* 우측: 상세 데이터 */}
<div className="flex-1">
<div className="glass-effect rounded-2xl h-full card-hover animate-slide-up flex flex-col">
{/* 상단 헤더 */}
<div className="p-4 border-b border-white/10 flex items-center justify-between">
<div>
<h3 className="text-lg font-semibold text-white flex items-center">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
<span>{selectedGroupCode ? `${selectedGroupCode} - ${selectedGroupName}` : '코드그룹을 선택하세요'}</span>
</h3>
<p className="text-white/70 text-sm mt-1"> <span className="text-white font-medium">{currentData.length}</span></p>
</div>
<button
onClick={showAddModal}
className="bg-white/20 hover:bg-white/30 backdrop-blur-sm text-white px-4 py-2 rounded-lg transition-all border border-white/30 flex items-center text-sm"
>
<svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
</svg>
추가
</button>
</div>
{/* 데이터 테이블 */}
<div className="flex-1 overflow-x-auto overflow-y-auto custom-scrollbar">
<table className="w-full">
<thead className="bg-white/10 sticky top-0">
<tr>
<th className="w-24 px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">코드</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">비고</th>
<th className="w-32 px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">(문자열)</th>
<th className="w-20 px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">(숫자)</th>
<th className="w-20 px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">(실수)</th>
<th className="w-24 px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">값2</th>
</tr>
</thead>
<tbody className="divide-y divide-white/10">
{currentData.length === 0 ? (
<tr>
<td colSpan="6" className="px-4 py-8 text-center text-white/70">
<svg className="w-12 h-12 mx-auto mb-2 text-white/30" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
{selectedGroupCode ? '데이터가 없습니다.' : '좌측에서 코드그룹을 선택하세요'}
</td>
</tr>
) : (
currentData.map(item => (
<tr
key={item.idx}
className="hover:bg-white/5 transition-colors cursor-pointer"
onClick={() => editItem(item.idx)}
>
<td className="px-4 py-4 whitespace-nowrap text-sm text-white">{item.code || '-'}</td>
<td className="px-4 py-4 text-sm text-white">{item.memo || '-'}</td>
<td className="px-4 py-4 text-sm text-white svalue-cell" title={item.svalue || '-'}>{item.svalue || '-'}</td>
<td className="px-4 py-4 whitespace-nowrap text-sm text-white">{item.ivalue || '0'}</td>
<td className="px-4 py-4 whitespace-nowrap text-sm text-white">{item.fvalue || '0.0'}</td>
<td className="px-4 py-4 whitespace-nowrap text-sm text-white">{item.svalue2 || '-'}</td>
</tr>
))
)}
</tbody>
</table>
</div>
</div>
</div>
</div>
{/* 로딩 인디케이터 */}
{isLoading && (
<div className="fixed top-4 right-4 bg-white/20 backdrop-blur-sm rounded-full px-4 py-2 text-white text-sm">
<div className="flex items-center">
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
데이터 로딩 ...
</div>
</div>
)}
{/* 추가/편집 모달 */}
{showEditModal && (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50">
<div className="flex items-center justify-center min-h-screen p-4">
<div className="glass-effect rounded-2xl w-full max-w-2xl animate-slide-up">
{/* 모달 헤더 */}
<div className="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 className="text-xl font-semibold text-white">
{isEditMode ? '공용코드 편집' : '공용코드 추가'}
</h2>
<button
onClick={() => setShowEditModal(false)}
className="text-white/70 hover:text-white transition-colors"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
{/* 모달 내용 */}
<form id="editForm" className="p-6">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-white/70 mb-2">코드그룹 *</label>
<select
value={editData.grp}
onChange={(e) => handleInputChange('grp', e.target.value)}
required
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
>
<option value="" className="bg-gray-800 text-white">선택하세요</option>
{groupData.map(group => (
<option key={group.code} value={group.code} className="bg-gray-800 text-white">
{group.code}-{group.memo}
</option>
))}
</select>
</div>
<div>
<label className="block text-sm font-medium text-white/70 mb-2">코드 *</label>
<input
type="text"
value={editData.code}
onChange={(e) => handleInputChange('code', e.target.value)}
required
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="코드를 입력하세요"
/>
</div>
<div>
<label className="block text-sm font-medium text-white/70 mb-2">(문자열)</label>
<input
type="text"
value={editData.svalue}
onChange={(e) => handleInputChange('svalue', e.target.value)}
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="문자열 값"
/>
</div>
<div>
<label className="block text-sm font-medium text-white/70 mb-2">(숫자)</label>
<input
type="number"
value={editData.ivalue}
onChange={(e) => handleInputChange('ivalue', e.target.value)}
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="숫자 값"
/>
</div>
<div>
<label className="block text-sm font-medium text-white/70 mb-2">(실수)</label>
<input
type="number"
step="0.01"
value={editData.fvalue}
onChange={(e) => handleInputChange('fvalue', e.target.value)}
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="실수 값"
/>
</div>
<div>
<label className="block text-sm font-medium text-white/70 mb-2">값2</label>
<input
type="text"
value={editData.svalue2}
onChange={(e) => handleInputChange('svalue2', e.target.value)}
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="추가 문자열 값"
/>
</div>
</div>
<div className="mt-4">
<label className="block text-sm font-medium text-white/70 mb-2">비고</label>
<textarea
value={editData.memo}
onChange={(e) => handleInputChange('memo', e.target.value)}
rows="3"
className="w-full px-3 py-2 bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="비고사항을 입력하세요"
></textarea>
</div>
</form>
{/* 모달 푸터 */}
<div className="px-6 py-4 border-t border-white/10 flex justify-between">
<button
onClick={deleteCurrentItem}
disabled={!isEditMode}
className={`bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-lg transition-colors flex items-center ${
!isEditMode ? 'opacity-50 cursor-not-allowed' : ''
}`}
>
<svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
</svg>
삭제
</button>
<div className="flex gap-2">
<button
onClick={() => setShowEditModal(false)}
className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors"
>
취소
</button>
<button
onClick={saveData}
className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors"
>
저장
</button>
</div>
</div>
</div>
</div>
</div>
)}
{/* 삭제 확인 모달 */}
{showDeleteModal && (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50">
<div className="flex items-center justify-center min-h-screen p-4">
<div className="glass-effect rounded-2xl w-full max-w-md animate-slide-up">
<div className="p-6">
<div className="flex items-center mb-4">
<div className="w-12 h-12 bg-red-100 rounded-full flex items-center justify-center mr-4">
<svg className="w-6 h-6 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.268 18.5c-.77.833.192 2.5 1.732 2.5z"></path>
</svg>
</div>
<div>
<h3 className="text-lg font-medium text-gray-900">삭제 확인</h3>
<p className="text-sm text-gray-500"> 작업은 되돌릴 없습니다.</p>
</div>
</div>
<p className="text-gray-700 mb-6">
선택한 공용코드를 삭제하시겠습니까?<br />
<span className="text-sm text-gray-500"> 작업은 되돌릴 없습니다.</span>
</p>
<div className="flex justify-end gap-2">
<button
onClick={() => { setShowDeleteModal(false); setDeleteTargetIdx(null); }}
className="bg-gray-300 hover:bg-gray-400 text-gray-700 px-4 py-2 rounded-lg transition-colors"
>
취소
</button>
<button
onClick={confirmDelete}
className="bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-lg transition-colors"
>
삭제
</button>
</div>
</div>
</div>
</div>
</div>
)}
</div>
);
}

View File

@@ -1,166 +0,0 @@
// CommonNavigation.jsx - React Navigation Component for GroupWare
const CommonNavigation = ({ currentPage = 'dashboard' }) => {
const [menuItems, setMenuItems] = useState([]);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const [currentUser, setCurrentUser] = useState('사용자');
// 기본 메뉴 아이템 - React 경로 사용
const defaultMenuItems = [
{
key: 'dashboard',
title: '대시보드',
url: '/react/dashboard',
icon: 'M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z M8 5a2 2 0 012-2h4a2 2 0 012 2v2H8V5z',
isVisible: true,
sortOrder: 1
},
{
key: 'common',
title: '공용코드',
url: '/react/common',
icon: 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z',
isVisible: true,
sortOrder: 2
},
{
key: 'jobreport',
title: '업무일지',
url: '/react/jobreport',
icon: 'M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2',
isVisible: true,
sortOrder: 3
},
{
key: 'kuntae',
title: '근태관리',
url: '/react/kuntae',
icon: 'M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z',
isVisible: true,
sortOrder: 4
},
{
key: 'todo',
title: '할일관리',
url: '/react/todo',
icon: 'M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2M12 12l2 2 4-4',
isVisible: true,
sortOrder: 5
},
{
key: 'project',
title: '프로젝트',
url: '/react/project',
icon: 'M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10',
isVisible: true,
sortOrder: 6
},
{
key: 'purchase',
title: '구매관리',
url: '/Purchase/',
icon: 'M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z',
isVisible: true,
sortOrder: 7
},
{
key: 'customer',
title: '고객관리',
url: '/Customer/',
icon: 'M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z',
isVisible: true,
sortOrder: 8
}
];
// 메뉴 아이템 로드 - defaultMenuItems 사용 (React 경로)
useEffect(() => {
setMenuItems(defaultMenuItems);
}, []);
// 보이는 메뉴 아이템만 정렬해서 반환
const visibleItems = menuItems
.filter(item => item.isVisible)
.sort((a, b) => a.sortOrder - b.sortOrder);
return (
<nav className="glass-effect border-b border-white/10 relative z-40">
<div className="container mx-auto px-4">
<div className="flex items-center justify-between h-16">
{/* 로고 및 브랜드 */}
<div className="flex items-center space-x-8">
<div className="flex items-center space-x-2">
<svg className="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z M8 5a2 2 0 012-2h4a2 2 0 012 2v2H8V5z"></path>
</svg>
<span className="text-xl font-bold text-white">GroupWare</span>
</div>
{/* 데스크톱 메뉴 */}
<nav className="hidden md:flex space-x-1">
{visibleItems.map(item => (
<a
key={item.key}
href={item.url}
className={`px-3 py-2 rounded-md text-sm font-medium transition-colors ${
currentPage === item.key
? 'bg-white/20 text-white'
: 'text-white/60 hover:text-white hover:bg-white/10'
}`}
>
<svg className="w-4 h-4 inline mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d={item.icon}></path>
</svg>
{item.title}
</a>
))}
</nav>
</div>
{/* 우측 메뉴 */}
<div className="flex items-center space-x-4">
<div className="text-sm text-white/60">
<span>{currentUser}</span>
</div>
{/* 모바일 메뉴 버튼 */}
<button
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
className="md:hidden text-white/60 hover:text-white focus:outline-none focus:text-white"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
{mobileMenuOpen ? (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"></path>
) : (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16M4 18h16"></path>
)}
</svg>
</button>
</div>
</div>
{/* 모바일 메뉴 */}
{mobileMenuOpen && (
<div className="md:hidden border-t border-white/10 py-2">
{visibleItems.map(item => (
<a
key={item.key}
href={item.url}
className={`block px-3 py-2 text-sm font-medium transition-colors ${
currentPage === item.key
? 'bg-white/20 text-white'
: 'text-white/60 hover:text-white hover:bg-white/10'
}`}
onClick={() => setMobileMenuOpen(false)}
>
<svg className="w-4 h-4 inline mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d={item.icon}></path>
</svg>
{item.title}
</a>
))}
</div>
)}
</div>
</nav>
);
};

View File

@@ -1,669 +0,0 @@
// DashboardApp.jsx - React Dashboard Component for GroupWare
const { useState, useEffect, useRef } = React;
function DashboardApp() {
// 상태 관리
const [dashboardData, setDashboardData] = useState({
presentCount: 0,
leaveCount: 0,
leaveRequestCount: 0,
purchaseCountNR: 0,
purchaseCountCR: 0
});
const [isLoading, setIsLoading] = useState(true);
const [lastUpdated, setLastUpdated] = useState('');
const [modals, setModals] = useState({
presentUsers: false,
holidayUsers: false,
holidayRequest: false,
purchaseNR: false,
purchaseCR: false
});
const [modalData, setModalData] = useState({
presentUsers: [],
holidayUsers: [],
holidayRequests: [],
purchaseNR: [],
purchaseCR: []
});
const [todoList, setTodoList] = useState([]);
// 모달 제어 함수
const showModal = (modalName) => {
setModals(prev => ({ ...prev, [modalName]: true }));
loadModalData(modalName);
};
const hideModal = (modalName) => {
setModals(prev => ({ ...prev, [modalName]: false }));
};
// Dashboard 데이터 로드
const loadDashboardData = async () => {
setIsLoading(true);
try {
// 실제 DashBoardController API 호출
const [
currentUserResponse,
leaveCountResponse,
holyRequestResponse,
purchaseWaitResponse
] = await Promise.all([
fetch('http://127.0.0.1:7979/DashBoard/GetCurrentUserCount'),
fetch('http://127.0.0.1:7979/DashBoard/TodayCountH'),
fetch('http://127.0.0.1:7979/DashBoard/GetHolydayRequestCount'),
fetch('http://127.0.0.1:7979/DashBoard/GetPurchaseWaitCount')
]);
// 현재 근무자 수 (JSON 응답)
const currentUserData = await currentUserResponse.json();
const presentCount = currentUserData.Count || 0;
// 휴가자 수 (텍스트 응답)
const leaveCountText = await leaveCountResponse.text();
const leaveCount = parseInt(leaveCountText.replace(/"/g, ''), 10) || 0;
// 휴가 요청 수 (JSON 응답)
const holyRequestData = await holyRequestResponse.json();
const leaveRequestCount = holyRequestData.HOLY || 0;
// 구매 대기 수 (JSON 응답)
const purchaseWaitData = await purchaseWaitResponse.json();
const purchaseCountNR = purchaseWaitData.NR || 0;
const purchaseCountCR = purchaseWaitData.CR || 0;
setDashboardData({
presentCount,
leaveCount,
leaveRequestCount,
purchaseCountNR,
purchaseCountCR
});
setLastUpdated(new Date().toLocaleString('ko-KR'));
} catch (error) {
console.error('대시보드 데이터 로드 실패:', error);
} finally {
setIsLoading(false);
}
};
// 모달 데이터 로드
const loadModalData = async (modalName) => {
try {
let endpoint = '';
switch (modalName) {
case 'presentUsers':
endpoint = 'http://127.0.0.1:7979/DashBoard/GetPresentUserList';
break;
case 'holidayUsers':
endpoint = 'http://127.0.0.1:7979/DashBoard/GetholyUser';
break;
case 'holidayRequest':
endpoint = 'http://127.0.0.1:7979/DashBoard/GetholyRequestUser';
break;
case 'purchaseNR':
endpoint = 'http://127.0.0.1:7979/DashBoard/GetPurchaseNRList';
break;
case 'purchaseCR':
endpoint = 'http://127.0.0.1:7979/DashBoard/GetPurchaseCRList';
break;
default:
return;
}
const response = await fetch(endpoint);
const data = await response.json();
setModalData(prev => ({
...prev,
[modalName]: Array.isArray(data) ? data : []
}));
} catch (error) {
console.error(`모달 데이터 로드 실패 (${modalName}):`, error);
setModalData(prev => ({
...prev,
[modalName]: []
}));
}
};
// Todo 목록 로드
const loadTodoList = async () => {
try {
const response = await fetch('http://127.0.0.1:7979/Todo/GetUrgentTodos');
const data = await response.json();
if (data.Success && data.Data) {
setTodoList(data.Data);
} else {
setTodoList([]);
}
} catch (error) {
console.error('Todo 목록 로드 실패:', error);
setTodoList([]);
}
};
// 자동 새로고침 (30초마다)
useEffect(() => {
loadDashboardData();
loadModalData('holidayUsers'); // 휴가자 목록 자동 로드
loadTodoList(); // Todo 목록 자동 로드
const interval = setInterval(() => {
loadDashboardData();
loadModalData('holidayUsers'); // 30초마다 휴가자 목록도 새로고침
loadTodoList(); // 30초마다 Todo 목록도 새로고침
}, 30000); // 30초
return () => clearInterval(interval);
}, []);
// 통계 카드 컴포넌트
const StatCard = ({ title, count, icon, color, onClick, isClickable = false }) => {
return (
<div
className={`glass-effect rounded-2xl p-6 card-hover animate-slide-up ${isClickable ? 'cursor-pointer' : ''}`}
onClick={onClick}
>
<div className="flex items-center justify-between">
<div>
<p className="text-white/70 text-sm font-medium">{title}</p>
<p className="text-3xl font-bold text-white">
{isLoading ? (
<div className="animate-pulse bg-white/20 h-8 w-16 rounded"></div>
) : count}
</p>
</div>
<div className={`w-12 h-12 ${color}/20 rounded-full flex items-center justify-center`}>
{icon}
</div>
</div>
</div>
);
};
// 테이블 모달 컴포넌트
const TableModal = ({ isOpen, onClose, title, headers, data, renderRow, maxWidth = 'max-w-4xl' }) => {
if (!isOpen) return null;
return (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50">
<div className="flex items-center justify-center min-h-screen p-4">
<div className={`glass-effect rounded-2xl w-full ${maxWidth} max-h-[80vh] overflow-hidden animate-slide-up`}>
{/* 모달 헤더 */}
<div className="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 className="text-xl font-semibold text-white flex items-center">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
{title}
</h2>
<button
onClick={onClose}
className="text-white/70 hover:text-white transition-colors"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
{/* 모달 내용 */}
<div className="overflow-x-auto max-h-[60vh] custom-scrollbar">
<table className="w-full">
<thead className="bg-white/10 sticky top-0">
<tr>
{headers.map((header, index) => (
<th key={index} className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">
{header}
</th>
))}
</tr>
</thead>
<tbody className="divide-y divide-white/10">
{data.length > 0 ? (
data.map((item, index) => renderRow(item, index))
) : (
<tr>
<td colSpan={headers.length} className="px-6 py-8 text-center text-white/50">
데이터가 없습니다.
</td>
</tr>
)}
</tbody>
</table>
</div>
{/* 모달 푸터 */}
<div className="px-6 py-4 border-t border-white/10 flex justify-between items-center">
<p className="text-white/70 text-sm">
<span className="font-medium">{data.length}</span>
</p>
<button
onClick={onClose}
className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors"
>
닫기
</button>
</div>
</div>
</div>
</div>
);
};
return (
<div className="bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 min-h-screen text-white">
<div className="container mx-auto px-4 py-8">
{/* 헤더 */}
<div className="text-center mb-8 animate-fade-in">
<h1 className="text-4xl font-bold mb-4">근태현황 대시보드</h1>
<p className="text-white/70">실시간 근태 업무 현황을 확인하세요</p>
{lastUpdated && (
<p className="text-white/50 text-sm mt-2">마지막 업데이트: {lastUpdated}</p>
)}
</div>
{/* 새로고침 버튼 */}
<div className="flex justify-end mb-6">
<button
onClick={loadDashboardData}
disabled={isLoading}
className="glass-effect rounded-lg px-4 py-2 text-white hover:bg-white/10 transition-all duration-300 disabled:opacity-50"
>
{isLoading ? (
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2 inline-block"></div>
) : (
<svg className="w-4 h-4 mr-2 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
</svg>
)}
새로고침
</button>
</div>
{/* 통계 카드 */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-6 mb-8">
<StatCard
title="출근(대상)"
count={dashboardData.presentCount}
isClickable={true}
onClick={() => showModal('presentUsers')}
color="bg-success-500"
icon={
<svg className="w-6 h-6 text-success-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
}
/>
<StatCard
title="휴가"
count={dashboardData.leaveCount}
isClickable={true}
onClick={() => showModal('holidayUsers')}
color="bg-warning-500"
icon={
<svg className="w-6 h-6 text-warning-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
}
/>
<StatCard
title="휴가요청"
count={dashboardData.leaveRequestCount}
isClickable={true}
onClick={() => showModal('holidayRequest')}
color="bg-primary-500"
icon={
<svg className="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
}
/>
<StatCard
title="구매요청(NR)"
count={dashboardData.purchaseCountNR}
isClickable={true}
onClick={() => showModal('purchaseNR')}
color="bg-danger-500"
icon={
<svg className="w-6 h-6 text-danger-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"></path>
</svg>
}
/>
<StatCard
title="구매요청(CR)"
count={dashboardData.purchaseCountCR}
isClickable={true}
onClick={() => showModal('purchaseCR')}
color="bg-purple-500"
icon={
<svg className="w-6 h-6 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z"></path>
</svg>
}
/>
</div>
{/* 2칸 레이아웃: 좌측 휴가현황, 우측 할일 */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 animate-slide-up">
{/* 좌측: 휴가/기타 현황 */}
<div className="glass-effect rounded-2xl overflow-hidden">
<div className="px-6 py-4 border-b border-white/10">
<h2 className="text-xl font-semibold text-white flex items-center">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path>
</svg>
휴가/기타 현황
</h2>
</div>
<div className="overflow-x-auto max-h-[460px] custom-scrollbar">
<table className="w-full">
<thead className="bg-white/10 sticky top-0">
<tr>
<th className="px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">이름</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">형태</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">종류</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">기간</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/70 uppercase tracking-wider">사유</th>
</tr>
</thead>
<tbody className="divide-y divide-white/10">
{modalData.holidayUsers.map((user, index) => {
// 형태에 따른 색상 결정
const typeColorClass = (user.type === '휴가') ? 'bg-green-500/20 text-green-300' : 'bg-warning-500/20 text-warning-300';
// 종류에 따른 색상 결정
let cateColorClass = 'bg-warning-500/20 text-warning-300'; // 기본값
if (user.cate === '휴가') {
cateColorClass = 'bg-warning-500/20 text-warning-300'; // 노란색 계열
} else if (user.cate === '파견') {
cateColorClass = 'bg-purple-500/20 text-purple-300'; // 보라색 계열
} else {
cateColorClass = 'bg-warning-500/20 text-warning-300'; // 기타는 주황색 계열
}
// 기간 표시 형식 개선
let periodText = '';
if (user.sdate && user.edate) {
if (user.sdate === user.edate) {
periodText = user.sdate;
} else {
periodText = `${user.sdate}~${user.edate}`;
}
} else {
periodText = '-';
}
return (
<tr key={index} className="hover:bg-white/5">
<td className="px-4 py-3 text-white text-sm font-medium">{user.name || '이름 없음'}</td>
<td className="px-4 py-3">
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${typeColorClass}`}>
{user.type || 'N/A'}
</span>
</td>
<td className="px-4 py-3">
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${cateColorClass}`}>
{user.cate || '종류 없음'}
</span>
</td>
<td className="px-4 py-3 text-white text-sm">{periodText}</td>
<td className="px-4 py-3 text-white/70 text-sm">{user.title || '사유 없음'}</td>
</tr>
);
})}
{modalData.holidayUsers.length === 0 && (
<tr>
<td colSpan="5" className="px-4 py-8 text-center text-white/50">
현재 휴가자가 없습니다
</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
{/* 우측: 할일 */}
<div className="glass-effect rounded-2xl overflow-hidden">
<div className="px-6 py-4 border-b border-white/10">
<h2 className="text-xl font-semibold text-white flex items-center justify-between">
<span className="flex items-center">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path>
</svg>
할일
</span>
<div className="flex items-center space-x-2">
<button
className="text-xs bg-primary-500/20 hover:bg-primary-500/30 text-primary-300 hover:text-primary-200 px-3 py-1 rounded-full transition-colors flex items-center"
onClick={() => alert('할일 추가 기능은 준비 중입니다.')}
>
<svg className="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
</svg>
할일추가
</button>
<button
className="text-xs bg-white/20 hover:bg-white/30 px-3 py-1 rounded-full transition-colors"
onClick={() => window.location.href = '/react/todo'}
>
전체보기
</button>
</div>
</h2>
</div>
<div className="p-4">
<div className="space-y-3 max-h-[384px] overflow-y-auto custom-scrollbar">
{todoList.length > 0 ? (
todoList.map((todo, index) => {
const flagIcon = todo.flag ? '📌 ' : '';
// 상태별 클래스
const getTodoStatusClass = (status) => {
switch(status) {
case '0': return 'bg-gray-500/20 text-gray-300';
case '1': return 'bg-primary-500/20 text-primary-300';
case '2': return 'bg-danger-500/20 text-danger-300';
case '3': return 'bg-warning-500/20 text-warning-300';
case '5': return 'bg-success-500/20 text-success-300';
default: return 'bg-white/10 text-white/50';
}
};
const getTodoStatusText = (status) => {
switch(status) {
case '0': return '대기';
case '1': return '진행';
case '2': return '취소';
case '3': return '보류';
case '5': return '완료';
default: return '대기';
}
};
const getTodoSeqnoClass = (seqno) => {
switch(seqno) {
case '0': return 'bg-gray-500/20 text-gray-300';
case '1': return 'bg-success-500/20 text-success-300';
case '2': return 'bg-warning-500/20 text-warning-300';
case '3': return 'bg-danger-500/20 text-danger-300';
default: return 'bg-white/10 text-white/50';
}
};
const getTodoSeqnoText = (seqno) => {
switch(seqno) {
case '0': return '낮음';
case '1': return '보통';
case '2': return '높음';
case '3': return '긴급';
default: return '보통';
}
};
const statusClass = getTodoStatusClass(todo.status);
const statusText = getTodoStatusText(todo.status);
const seqnoClass = getTodoSeqnoClass(todo.seqno);
const seqnoText = getTodoSeqnoText(todo.seqno);
const expireText = todo.expire ? new Date(todo.expire).toLocaleDateString('ko-KR') : '';
const isExpired = todo.expire && new Date(todo.expire) < new Date();
const expireClass = isExpired ? 'text-danger-400' : 'text-white/60';
// 만료일이 지난 경우 배경을 적색계통으로 강조
const expiredBgClass = isExpired ? 'bg-danger-600/30 border-danger-400/40 hover:bg-danger-600/40' : 'bg-white/10 hover:bg-white/15 border-white/20';
return (
<div key={index} className={`${expiredBgClass} backdrop-blur-sm rounded-lg p-3 transition-colors cursor-pointer border`}
onClick={() => alert('Todo 상세보기 기능은 준비 중입니다.')}>
<div className="flex items-start justify-between mb-2">
<div className="flex items-center gap-1">
<span className={`inline-flex items-center px-2 py-1 rounded-full text-xs font-medium ${statusClass}`}>
{statusText}
</span>
<span className={`inline-flex items-center px-2 py-1 rounded-full text-xs font-medium ${seqnoClass}`}>
{seqnoText}
</span>
</div>
{expireText && (
<span className={`text-xs ${expireClass}`}>
{expireText}
</span>
)}
</div>
<p className="text-white text-sm font-medium mb-1">
{flagIcon}{todo.title || '제목 없음'}
</p>
{todo.description && (
<p className="text-white/70 text-xs mb-2 line-clamp-2">
{todo.description}
</p>
)}
{todo.request && (
<p className="text-white/50 text-xs mt-2">요청자: {todo.request}</p>
)}
</div>
);
})
) : (
<div className="text-center text-white/50 py-8">
<svg className="w-8 h-8 mx-auto mb-2 opacity-50" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path>
</svg>
급한 할일이 없습니다
</div>
)}
</div>
</div>
</div>
</div>
{/* 출근 대상자 모달 */}
<TableModal
isOpen={modals.presentUsers}
onClose={() => hideModal('presentUsers')}
title="금일 출근 대상자 목록"
headers={['사번', '이름', '공정', '직급', '상태', '이메일']}
data={modalData.presentUsers}
renderRow={(user, index) => (
<tr key={index} className="hover:bg-white/5">
<td className="px-6 py-4 text-white text-sm">{user.id || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">{user.name || '이름 없음'}</td>
<td className="px-6 py-4 text-white text-sm">{user.gname || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">{user.level || 'N/A'}</td>
<td className="px-6 py-4 text-success-400 text-sm">출근</td>
<td className="px-6 py-4 text-white/70 text-sm">{user.email || 'N/A'}</td>
</tr>
)}
/>
{/* 휴가 요청 모달 */}
<TableModal
isOpen={modals.holidayRequest}
onClose={() => hideModal('holidayRequest')}
title="휴가 신청 목록"
maxWidth="max-w-6xl"
headers={['사번', '이름', '항목', '일자', '요청일', '요청시간', '비고']}
data={modalData.holidayRequests}
renderRow={(request, index) => (
<tr key={index} className="hover:bg-white/5">
<td className="px-6 py-4 text-white text-sm">{request.uid || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">{request.name || '이름 없음'}</td>
<td className="px-6 py-4 text-white text-sm">{request.cate || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">
{request.sdate && request.edate ? `${request.sdate} ~ ${request.edate}` : 'N/A'}
</td>
<td className="px-6 py-4 text-white text-sm">{request.holydays || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">{request.holytimes || 'N/A'}</td>
<td className="px-6 py-4 text-white/70 text-sm">{request.HolyReason || request.remark || 'N/A'}</td>
</tr>
)}
/>
{/* 구매요청 NR 모달 */}
<TableModal
isOpen={modals.purchaseNR}
onClose={() => hideModal('purchaseNR')}
title="구매요청(NR) 목록"
maxWidth="max-w-7xl"
headers={['요청일', '공정', '품목', '규격', '단위', '수량', '단가', '금액']}
data={modalData.purchaseNR}
renderRow={(item, index) => (
<tr key={index} className="hover:bg-white/5">
<td className="px-6 py-4 text-white text-sm">{item.pdate || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">{item.process || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">{item.pumname || '품목 없음'}</td>
<td className="px-6 py-4 text-white text-sm">{item.pumscale || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">{item.pumunit || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">{item.pumqtyreq || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">
{item.pumprice ? `${Number(item.pumprice).toLocaleString()}` : 'N/A'}
</td>
<td className="px-6 py-4 text-danger-400 text-sm font-medium">
{item.pumamt ? `${Number(item.pumamt).toLocaleString()}` : 'N/A'}
</td>
</tr>
)}
/>
{/* 구매요청 CR 모달 */}
<TableModal
isOpen={modals.purchaseCR}
onClose={() => hideModal('purchaseCR')}
title="구매요청(CR) 목록"
maxWidth="max-w-7xl"
headers={['요청일', '공정', '품목', '규격', '단위', '수량', '단가', '금액']}
data={modalData.purchaseCR}
renderRow={(item, index) => (
<tr key={index} className="hover:bg-white/5">
<td className="px-6 py-4 text-white text-sm">{item.pdate || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">{item.process || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">{item.pumname || '품목 없음'}</td>
<td className="px-6 py-4 text-white text-sm">{item.pumscale || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">{item.pumunit || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">{item.pumqtyreq || 'N/A'}</td>
<td className="px-6 py-4 text-white text-sm">
{item.pumprice ? `${Number(item.pumprice).toLocaleString()}` : 'N/A'}
</td>
<td className="px-6 py-4 text-purple-400 text-sm font-medium">
{item.pumamt ? `${Number(item.pumamt).toLocaleString()}` : 'N/A'}
</td>
</tr>
)}
/>
</div>
</div>
);
}

View File

@@ -1,21 +0,0 @@
// 개발중 경고 메시지 컴포넌트
function DevWarning({ show = false }) {
// show props가 false이거나 없으면 아무것도 렌더링하지 않음
if (!show) {
return null;
}
return (
<div className="dev-warning animate-slide-up">
<div className="flex items-center">
<svg className="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path>
</svg>
<div>
<p className="title">🚧 개발중인 기능입니다</p>
<p className="description">일부 기능이 정상적으로 동작하지 않을 있습니다.</p>
</div>
</div>
</div>
);
}

View File

@@ -1,988 +0,0 @@
const { useState, useEffect } = React;
function JobReport() {
// 상태 관리
const [jobData, setJobData] = useState([]);
const [filteredData, setFilteredData] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(25);
const [sortColumn, setSortColumn] = useState('pdate');
const [sortDirection, setSortDirection] = useState('desc');
const [isLoading, setIsLoading] = useState(false);
const [showEditModal, setShowEditModal] = useState(false);
const [editData, setEditData] = useState({});
const [isEditMode, setIsEditMode] = useState(false);
// 필터 상태
const [filters, setFilters] = useState({
startDate: '',
endDate: '',
status: '',
type: '',
user: '',
project: '',
search: ''
});
// 통계 데이터
const [statistics, setStatistics] = useState({
totalDays: 0,
todayHours: 0,
todayProgress: 0,
totalOT: 0,
activeProjects: 0
});
// 컴포넌트 마운트시 초기화
useEffect(() => {
initializeFilters();
loadJobData();
loadUserList();
}, []);
// 필터 변경 시 데이터 필터링
useEffect(() => {
filterData();
}, [jobData, filters]);
// 초기 필터 설정 (오늘부터 -2주)
const initializeFilters = () => {
const now = new Date();
const today = now.toISOString().split('T')[0];
const twoWeeksAgo = new Date(now.getTime() - (14 * 24 * 60 * 60 * 1000)).toISOString().split('T')[0];
setFilters(prev => ({
...prev,
startDate: twoWeeksAgo,
endDate: today
}));
};
// 업무일지 데이터 로드
const loadJobData = async () => {
setIsLoading(true);
try {
let url = '/Jobreport/GetJobData';
const params = new URLSearchParams();
if (filters.startDate) params.append('startDate', filters.startDate);
if (filters.endDate) params.append('endDate', filters.endDate);
if (filters.user) params.append('user', filters.user);
if (params.toString()) {
url += '?' + params.toString();
}
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: 데이터를 불러오는데 실패했습니다.`);
}
const responseText = await response.text();
const responseData = JSON.parse(responseText);
if (Array.isArray(responseData)) {
setJobData(responseData);
} else if (responseData.error) {
throw new Error(responseData.error);
} else {
setJobData([]);
}
} catch (error) {
console.error('Error loading job data:', error);
setJobData([]);
showNotification('데이터를 불러오는데 실패했습니다: ' + error.message, 'error');
} finally {
setIsLoading(false);
}
};
// 사용자 목록 로드
const loadUserList = async () => {
try {
const response = await fetch('/Jobreport/GetUsers');
if (response.ok) {
const data = await response.json();
// 사용자 데이터를 상태로 저장 (필요시)
}
} catch (error) {
console.error('사용자 목록 로드 중 오류:', error);
}
};
// 통계 업데이트
useEffect(() => {
updateStatistics();
}, [jobData]);
const updateStatistics = () => {
const totalDays = new Set(jobData.map(item => item.pdate)).size;
const totalOT = jobData.reduce((sum, item) => sum + (parseFloat(item.ot) || 0), 0);
const activeProjects = new Set(jobData.filter(item => item.status === '진행중').map(item => item.projectName)).size;
const now = new Date();
const today = now.toISOString().split('T')[0];
const todayData = jobData.filter(item => {
if (!item.pdate) return false;
const itemDate = item.pdate.toString();
if (itemDate.length >= 10) {
return itemDate.substring(0, 10) === today;
}
return false;
});
let todayHours = 0;
if (todayData.length > 0) {
todayHours = todayData.reduce((sum, item) => sum + (parseFloat(item.hrs) || 0), 0);
}
const todayProgress = (todayHours / 8) * 100;
setStatistics({
totalDays,
todayHours,
todayProgress,
totalOT,
activeProjects
});
};
// 데이터 필터링
const filterData = () => {
let filtered = jobData.filter(item => {
const statusMatch = !filters.status || item.status === filters.status;
const typeMatch = !filters.type || item.type === filters.type;
const projectMatch = !filters.project || item.projectName === filters.project;
const searchMatch = !filters.search ||
(item.description && item.description.toLowerCase().includes(filters.search.toLowerCase())) ||
(item.projectName && item.projectName.toLowerCase().includes(filters.search.toLowerCase())) ||
(item.requestpart && item.requestpart.toLowerCase().includes(filters.search.toLowerCase()));
return statusMatch && typeMatch && projectMatch && searchMatch;
});
// 정렬
filtered.sort((a, b) => {
let aVal = a[sortColumn];
let bVal = b[sortColumn];
if (sortColumn === 'pdate') {
aVal = new Date(aVal);
bVal = new Date(bVal);
} else if (['hrs', 'ot'].includes(sortColumn)) {
aVal = parseFloat(aVal) || 0;
bVal = parseFloat(bVal) || 0;
} else {
aVal = (aVal || '').toString().toLowerCase();
bVal = (bVal || '').toString().toLowerCase();
}
if (aVal < bVal) return sortDirection === 'asc' ? -1 : 1;
if (aVal > bVal) return sortDirection === 'asc' ? 1 : -1;
return 0;
});
setFilteredData(filtered);
setCurrentPage(1);
};
// 필터 변경 핸들러
const handleFilterChange = (field, value) => {
setFilters(prev => ({ ...prev, [field]: value }));
// 날짜 필터 변경시 데이터 다시 로드
if (field === 'startDate' || field === 'endDate' || field === 'user') {
setTimeout(() => loadJobData(), 100);
}
};
// 필터 초기화
const clearFilters = () => {
const now = new Date();
const today = now.toISOString().split('T')[0];
const twoWeeksAgo = new Date(now.getTime() - (14 * 24 * 60 * 60 * 1000)).toISOString().split('T')[0];
setFilters({
startDate: twoWeeksAgo,
endDate: today,
status: '',
type: '',
user: '',
project: '',
search: ''
});
setTimeout(() => loadJobData(), 100);
};
// 정렬 처리
const handleSort = (column) => {
if (sortColumn === column) {
setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc');
} else {
setSortColumn(column);
setSortDirection('asc');
}
};
// 추가 모달 표시
const showAddJobModal = () => {
const today = new Date().toISOString().split('T')[0];
setIsEditMode(false);
setEditData({
idx: '',
pdate: today,
status: '진행 중',
projectName: '',
requestpart: '',
type: '',
hrs: '8',
ot: '',
otStart: '',
otEnd: '',
description: ''
});
setShowEditModal(true);
};
// 편집 모달 표시
const showEditJobModal = async (item) => {
try {
// 상세 정보 로드
const response = await fetch(`/Jobreport/GetJobDetail?id=${item.idx}`);
if (response.ok) {
const fullItem = await response.json();
item = fullItem.error ? item : fullItem;
}
} catch (error) {
console.warn('Failed to load full details, using truncated data:', error);
}
setIsEditMode(true);
setEditData({
idx: item.idx || '',
pdate: item.pdate || '',
status: item.status || '',
projectName: item.projectName || '',
requestpart: item.requestpart || '',
type: item.type || '',
hrs: item.hrs || '',
ot: item.ot || '',
otStart: item.otStart || '',
otEnd: item.otEnd || '',
description: item.description || ''
});
setShowEditModal(true);
};
// 저장 처리
const handleSave = async (event) => {
event.preventDefault();
const formData = new URLSearchParams();
Object.keys(editData).forEach(key => {
if (key !== 'idx' || editData.idx) {
formData.append(key, editData[key]);
}
});
try {
const url = isEditMode ? '/Jobreport/Edit' : '/Jobreport/Add';
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formData
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${isEditMode ? '수정' : '추가'}에 실패했습니다.`);
}
setShowEditModal(false);
await loadJobData();
showNotification(`업무일지가 성공적으로 ${isEditMode ? '수정' : '추가'}되었습니다.`, 'success');
} catch (error) {
console.error('Error saving job:', error);
showNotification(`업무일지 ${isEditMode ? '수정' : '추가'} 중 오류가 발생했습니다: ` + error.message, 'error');
}
};
// 삭제 처리
const handleDelete = async () => {
if (!editData.idx) {
showNotification('삭제할 수 없는 항목입니다.', 'warning');
return;
}
if (!window.confirm('정말로 이 업무일지를 삭제하시겠습니까?')) {
return;
}
try {
const response = await fetch(`/Jobreport/Delete/${editData.idx}`, {
method: 'DELETE'
});
if (!response.ok) {
throw new Error('삭제에 실패했습니다.');
}
const result = await response.json();
if (result.success) {
setShowEditModal(false);
await loadJobData();
showNotification('업무일지가 성공적으로 삭제되었습니다.', 'success');
} else {
throw new Error(result.message || '삭제에 실패했습니다.');
}
} catch (error) {
console.error('Error deleting job:', error);
showNotification('업무일지 삭제 중 오류가 발생했습니다: ' + error.message, 'error');
}
};
// 엑셀 내보내기
const exportToExcel = () => {
if (filteredData.length === 0) {
showNotification('내보낼 데이터가 없습니다.', 'warning');
return;
}
const periodText = filters.startDate && filters.endDate ? `_${filters.startDate}_${filters.endDate}` : '';
const headers = ['날짜', '상태', '프로젝트명', '요청부서', '타입', '업무내용', '근무시간', '초과근무'];
const csvContent = [
headers.join(','),
...filteredData.map(item => [
formatDate(item.pdate),
item.status || '',
item.projectName || '',
item.requestpart || '',
item.type || '',
`"${(item.description || '').replace(/"/g, '""')}"`,
item.hrs || '',
item.ot || ''
].join(','))
].join('\n');
const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', `업무일지${periodText}_${new Date().toISOString().split('T')[0]}.csv`);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
// 유틸리티 함수들
const formatDate = (dateString) => {
if (!dateString) return '-';
const date = new Date(dateString);
return date.toLocaleDateString('ko-KR');
};
const getStatusColor = (status) => {
switch (status) {
case '진행 중': return 'bg-blue-100 text-blue-800';
case '진행 완료': return 'bg-green-100 text-green-800';
case '대기': return 'bg-yellow-100 text-yellow-800';
default: return 'bg-gray-100 text-gray-800';
}
};
// 알림 표시 함수
const showNotification = (message, type = 'info') => {
const colors = {
info: 'bg-blue-500/90 backdrop-blur-sm',
success: 'bg-green-500/90 backdrop-blur-sm',
warning: 'bg-yellow-500/90 backdrop-blur-sm',
error: 'bg-red-500/90 backdrop-blur-sm'
};
const notification = document.createElement('div');
notification.className = `fixed top-4 right-4 ${colors[type]} text-white px-4 py-3 rounded-lg z-50 transition-all duration-300 transform translate-x-0 opacity-100 shadow-lg border border-white/20`;
notification.innerHTML = `
<div class="flex items-center">
<span class="ml-2">${message}</span>
</div>
`;
notification.style.transform = 'translateX(100%)';
notification.style.opacity = '0';
document.body.appendChild(notification);
setTimeout(() => {
notification.style.transform = 'translateX(0)';
notification.style.opacity = '1';
}, 10);
setTimeout(() => {
notification.style.transform = 'translateX(100%)';
notification.style.opacity = '0';
setTimeout(() => notification.remove(), 300);
}, 3000);
};
// 페이지네이션
const maxPage = Math.ceil(filteredData.length / pageSize);
const startIndex = (currentPage - 1) * pageSize;
const endIndex = startIndex + pageSize;
const pageData = filteredData.slice(startIndex, endIndex);
// 프로젝트 목록 업데이트
const uniqueProjects = [...new Set(jobData.map(item => item.projectName).filter(Boolean))];
return (
<div className="container mx-auto px-4 py-8">
{/* 개발중 경고 메시지 */}
<div className="bg-orange-500 rounded-lg p-4 mb-6 border-l-4 border-orange-700 animate-slide-up shadow-lg">
<div className="flex items-center">
<svg className="w-5 h-5 text-orange-900 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path>
</svg>
<div>
<p className="text-white font-bold text-base">🚧 개발중인 기능입니다</p>
<p className="text-orange-100 text-sm font-medium">일부 기능이 정상적으로 동작하지 않을 있습니다.</p>
</div>
</div>
</div>
{/* 통계 카드 */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8 animate-slide-up">
<div className="glass-effect rounded-lg p-6 card-hover">
<div className="flex items-center">
<div className="p-3 bg-primary-500/20 rounded-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
</div>
<div className="ml-4">
<p className="text-sm font-medium text-white/80"> 업무일수</p>
<p className="text-2xl font-bold text-white">{statistics.totalDays}</p>
</div>
</div>
</div>
<div className="glass-effect rounded-lg p-6 card-hover">
<div className="flex items-center">
<div className="p-3 bg-success-500/20 rounded-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<div className="ml-4">
<p className="text-sm font-medium text-white/80">오늘 근무시간</p>
<p className={`text-2xl font-bold ${statistics.todayHours < 8 ? 'text-red-300' : 'text-green-300'}`}>
{statistics.todayHours.toFixed(1)}h
</p>
<p className="text-sm text-white/60">(목표 8시간의 {statistics.todayProgress.toFixed(0)}%)</p>
</div>
</div>
</div>
<div className="glass-effect rounded-lg p-6 card-hover">
<div className="flex items-center">
<div className="p-3 bg-warning-500/20 rounded-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
</svg>
</div>
<div className="ml-4">
<p className="text-sm font-medium text-white/80"> 초과근무</p>
<p className="text-2xl font-bold text-white">{statistics.totalOT.toFixed(1)}h</p>
</div>
</div>
</div>
<div className="glass-effect rounded-lg p-6 card-hover">
<div className="flex items-center">
<div className="p-3 bg-purple-500/20 rounded-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z"></path>
</svg>
</div>
<div className="ml-4">
<p className="text-sm font-medium text-white/80">진행중 프로젝트</p>
<p className="text-2xl font-bold text-white">{statistics.activeProjects}</p>
</div>
</div>
</div>
</div>
{/* 필터 및 검색 */}
<div className="glass-effect rounded-lg mb-6 animate-slide-up">
<div className="p-4">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
{/* 좌측: 필터 컨트롤 */}
<div className="lg:col-span-2 space-y-3">
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
<div>
<label className="block text-xs font-medium text-white/80 mb-1">조회기간</label>
<div className="flex space-x-1">
<input
type="date"
value={filters.startDate}
onChange={(e) => handleFilterChange('startDate', e.target.value)}
className="flex-1 bg-white/20 border border-white/30 rounded-md px-2 py-1 text-white placeholder-white/60 focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent text-xs"
/>
<span className="flex items-center text-white/60 text-xs">~</span>
<input
type="date"
value={filters.endDate}
onChange={(e) => handleFilterChange('endDate', e.target.value)}
className="flex-1 bg-white/20 border border-white/30 rounded-md px-2 py-1 text-white placeholder-white/60 focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent text-xs"
/>
</div>
</div>
<div>
<label className="block text-xs font-medium text-white/80 mb-1">상태</label>
<select
value={filters.status}
onChange={(e) => handleFilterChange('status', e.target.value)}
className="w-full bg-white/20 border border-white/30 rounded-md px-2 py-1 text-white focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent text-xs"
>
<option value="">전체</option>
<option value="진행중">진행중</option>
<option value="완료">완료</option>
<option value="대기">대기</option>
</select>
</div>
<div>
<label className="block text-xs font-medium text-white/80 mb-1">타입</label>
<select
value={filters.type}
onChange={(e) => handleFilterChange('type', e.target.value)}
className="w-full bg-white/20 border border-white/30 rounded-md px-2 py-1 text-white focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent text-xs"
>
<option value="">전체</option>
<option value="개발">개발</option>
<option value="유지보수">유지보수</option>
<option value="분석">분석</option>
<option value="테스트">테스트</option>
<option value="문서작업">문서작업</option>
<option value="회의">회의</option>
<option value="기타">기타</option>
</select>
</div>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
<div>
<label className="block text-xs font-medium text-white/80 mb-1">프로젝트</label>
<select
value={filters.project}
onChange={(e) => handleFilterChange('project', e.target.value)}
className="w-full bg-white/20 border border-white/30 rounded-md px-2 py-1 text-white focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent text-xs"
>
<option value="">전체</option>
{uniqueProjects.map(project => (
<option key={project} value={project}>{project}</option>
))}
</select>
</div>
<div>
<label className="block text-xs font-medium text-white/80 mb-1">검색</label>
<input
type="text"
value={filters.search}
onChange={(e) => handleFilterChange('search', e.target.value)}
placeholder="업무 내용 검색..."
className="w-full bg-white/20 border border-white/30 rounded-md px-2 py-1 text-white placeholder-white/60 focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent text-xs"
/>
</div>
</div>
</div>
{/* 우측: 액션 버튼들 */}
<div className="flex flex-col space-y-2 justify-center">
<button
onClick={showAddJobModal}
className="bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-md flex items-center justify-center transition-colors"
>
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
</svg>
업무일지 추가
</button>
<button
onClick={exportToExcel}
className="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-md flex items-center justify-center transition-colors"
>
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
엑셀 다운로드
</button>
<button
onClick={clearFilters}
className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-md flex items-center justify-center transition-colors"
>
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
</svg>
필터 초기화
</button>
</div>
</div>
</div>
</div>
{/* 데이터 테이블 */}
<div className="glass-effect rounded-lg overflow-hidden animate-slide-up custom-scrollbar">
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-white/20">
<thead className="bg-white/10">
<tr>
<th
className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider cursor-pointer hover:bg-white/20 transition-colors"
onClick={() => handleSort('pdate')}
>
날짜 <svg className="w-4 h-4 inline ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 9l-7 7-7-7"></path>
</svg>
</th>
<th
className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider cursor-pointer hover:bg-white/20 transition-colors"
onClick={() => handleSort('status')}
>
상태 <svg className="w-4 h-4 inline ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 9l-7 7-7-7"></path>
</svg>
</th>
<th
className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider cursor-pointer hover:bg-white/20 transition-colors"
onClick={() => handleSort('hrs')}
>
근무시간 <svg className="w-4 h-4 inline ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 9l-7 7-7-7"></path>
</svg>
</th>
<th
className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider cursor-pointer hover:bg-white/20 transition-colors"
onClick={() => handleSort('projectName')}
>
프로젝트명 <svg className="w-4 h-4 inline ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 9l-7 7-7-7"></path>
</svg>
</th>
<th className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">업무내용</th>
<th
className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider cursor-pointer hover:bg-white/20 transition-colors"
onClick={() => handleSort('requestpart')}
>
요청부서 <svg className="w-4 h-4 inline ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 9l-7 7-7-7"></path>
</svg>
</th>
<th
className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider cursor-pointer hover:bg-white/20 transition-colors"
onClick={() => handleSort('type')}
>
타입 <svg className="w-4 h-4 inline ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 9l-7 7-7-7"></path>
</svg>
</th>
</tr>
</thead>
<tbody className="divide-y divide-white/10">
{isLoading ? (
<tr>
<td colSpan="7" className="p-8 text-center">
<div className="inline-flex items-center">
<svg className="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span className="text-white/80">데이터를 불러오는 ...</span>
</div>
</td>
</tr>
) : pageData.length === 0 ? (
<tr>
<td colSpan="7" className="p-8 text-center">
<svg className="w-12 h-12 text-white/60 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"></path>
</svg>
<p className="text-white/70">업무일지 데이터가 없습니다.</p>
</td>
</tr>
) : (
pageData.map((item, index) => {
const hrs = parseFloat(item.hrs) || 0;
const ot = parseFloat(item.ot) || 0;
let workTimeDisplay = '';
if (hrs > 0) {
workTimeDisplay = hrs.toFixed(1);
if (ot > 0) {
workTimeDisplay += '+' + ot.toFixed(1);
}
} else {
workTimeDisplay = '-';
}
return (
<tr
key={item.idx || index}
className="hover:bg-white/10 cursor-pointer transition-colors"
onClick={() => showEditJobModal(item)}
>
<td className="px-6 py-4 whitespace-nowrap text-sm text-white">
{formatDate(item.pdate)}
</td>
<td className="px-6 py-4 whitespace-nowrap">
<span className={`inline-flex px-2 py-1 text-xs font-semibold rounded-full ${getStatusColor(item.status)}`}>
{item.status || '-'}
</span>
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-white">
{workTimeDisplay}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-white">
<div className="flex items-center">
<span>{item.projectName || '-'}</span>
</div>
</td>
<td className="px-6 py-4 text-sm text-white">
<div className="max-w-xs truncate" title={item.description || ''}>
{item.description || '-'}
</div>
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-white">
{item.requestpart || '-'}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-white">
{item.type || '-'}
</td>
</tr>
);
})
)}
</tbody>
</table>
</div>
</div>
{/* 페이지네이션 */}
<div className="mt-6 flex items-center justify-between glass-effect rounded-lg p-4">
<div className="flex items-center space-x-2">
<span className="text-sm text-white/80">페이지당 :</span>
<select
value={pageSize}
onChange={(e) => {
setPageSize(parseInt(e.target.value));
setCurrentPage(1);
}}
className="bg-white/20 border border-white/30 rounded-md px-2 py-1 text-sm text-white"
>
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
<div className="flex items-center space-x-2">
<button
onClick={() => setCurrentPage(Math.max(1, currentPage - 1))}
disabled={currentPage <= 1}
className="px-3 py-1 border border-white/30 rounded-md text-sm text-white hover:bg-white/20 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
이전
</button>
<span className="text-sm text-white/80">{currentPage} / {maxPage}</span>
<button
onClick={() => setCurrentPage(Math.min(maxPage, currentPage + 1))}
disabled={currentPage >= maxPage}
className="px-3 py-1 border border-white/30 rounded-md text-sm text-white hover:bg-white/20 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
>
다음
</button>
</div>
</div>
{/* 편집 모달 */}
{showEditModal && (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50">
<div className="flex items-center justify-center min-h-screen p-4">
<div className="glass-effect rounded-2xl w-full max-w-6xl animate-slide-up">
{/* 모달 헤더 */}
<div className="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 className="text-xl font-semibold text-white flex items-center">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
</svg>
업무일지 {isEditMode ? '편집' : '추가'}
</h2>
<button
onClick={() => setShowEditModal(false)}
className="text-white/70 hover:text-white transition-colors"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
{/* 모달 내용 */}
<form onSubmit={handleSave} className="p-6">
<div className="grid grid-cols-1 lg:grid-cols-5 gap-8">
{/* 좌측: 기본 정보 */}
<div className="lg:col-span-2">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-white/70 text-sm font-medium mb-2">날짜 *</label>
<input
type="date"
value={editData.pdate || ''}
onChange={(e) => setEditData(prev => ({...prev, pdate: e.target.value}))}
required
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
/>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">상태 *</label>
<select
value={editData.status || ''}
onChange={(e) => setEditData(prev => ({...prev, status: e.target.value}))}
required
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
>
<option value="">선택하세요</option>
<option value="진행 중">진행 </option>
<option value="완료">완료</option>
<option value="대기">대기</option>
<option value="보류">보류</option>
</select>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">요청부서</label>
<input
type="text"
value={editData.requestpart || ''}
onChange={(e) => setEditData(prev => ({...prev, requestpart: e.target.value}))}
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
/>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">타입</label>
<select
value={editData.type || ''}
onChange={(e) => setEditData(prev => ({...prev, type: e.target.value}))}
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
>
<option value="">선택하세요</option>
<option value="개발">개발</option>
<option value="유지보수">유지보수</option>
<option value="분석">분석</option>
<option value="테스트">테스트</option>
<option value="문서작업">문서작업</option>
<option value="회의">회의</option>
<option value="기타">기타</option>
</select>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">근무시간 (시간) *</label>
<input
type="number"
step="any"
value={editData.hrs || ''}
onChange={(e) => setEditData(prev => ({...prev, hrs: e.target.value}))}
required
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
/>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">초과근무 (시간)</label>
<input
type="number"
step="any"
value={editData.ot || ''}
onChange={(e) => setEditData(prev => ({...prev, ot: e.target.value}))}
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
/>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">초과근무 시작시간</label>
<input
type="time"
value={editData.otStart || ''}
onChange={(e) => setEditData(prev => ({...prev, otStart: e.target.value}))}
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
/>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">초과근무 종료시간</label>
<input
type="time"
value={editData.otEnd || ''}
onChange={(e) => setEditData(prev => ({...prev, otEnd: e.target.value}))}
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
/>
</div>
</div>
</div>
{/* 우측: 프로젝트명과 업무내용 */}
<div className="lg:col-span-3 space-y-4">
<div>
<label className="block text-white/70 text-sm font-medium mb-2">프로젝트명 *</label>
<input
type="text"
value={editData.projectName || ''}
onChange={(e) => setEditData(prev => ({...prev, projectName: e.target.value}))}
required
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
/>
</div>
<div className="flex-grow">
<label className="block text-white/70 text-sm font-medium mb-2">업무내용 *</label>
<textarea
value={editData.description || ''}
onChange={(e) => setEditData(prev => ({...prev, description: e.target.value}))}
rows="15"
required
className="w-full h-full min-h-[360px] bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all resize-vertical"
placeholder="상세한 업무 내용을 입력하세요..."
/>
</div>
</div>
</div>
</form>
{/* 모달 푸터 */}
<div className="px-6 py-4 border-t border-white/10 flex justify-between items-center bg-black/10 rounded-b-2xl">
{isEditMode && (
<button
type="button"
onClick={handleDelete}
className="bg-danger-500 hover:bg-danger-600 text-white px-4 py-2 rounded-lg transition-colors"
>
삭제
</button>
)}
<div className="flex space-x-3 ml-auto">
<button
type="button"
onClick={() => setShowEditModal(false)}
className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors"
>
취소
</button>
<button
type="submit"
onClick={handleSave}
className="bg-primary-500 hover:bg-primary-600 text-white px-6 py-2 rounded-lg transition-colors"
>
저장
</button>
</div>
</div>
</div>
</div>
</div>
)}
</div>
);
}

View File

@@ -1,339 +0,0 @@
const { useState, useEffect } = React;
function Kuntae() {
// 상태 관리
const [kuntaeData, setKuntaeData] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [filters, setFilters] = useState({
startDate: '',
endDate: ''
});
// 통계 데이터
const [statistics, setStatistics] = useState({
totalDays: 0,
approvedDays: 0,
pendingDays: 0,
rejectedDays: 0
});
// 컴포넌트 마운트시 초기화
useEffect(() => {
initializeFilters();
}, []);
// 초기 필터 설정 (이번 달)
const initializeFilters = () => {
const now = new Date();
const firstDay = new Date(now.getFullYear(), now.getMonth(), 1);
const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0);
setFilters({
startDate: firstDay.toISOString().split('T')[0],
endDate: lastDay.toISOString().split('T')[0]
});
// 초기 데이터 로드
loadKuntaeData({
startDate: firstDay.toISOString().split('T')[0],
endDate: lastDay.toISOString().split('T')[0]
});
};
// 근태 데이터 로드
const loadKuntaeData = async (searchFilters = filters) => {
setIsLoading(true);
try {
let url = '/Kuntae/GetData';
const params = new URLSearchParams();
if (searchFilters.startDate) params.append('startDate', searchFilters.startDate);
if (searchFilters.endDate) params.append('endDate', searchFilters.endDate);
if (params.toString()) {
url += '?' + params.toString();
}
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: 데이터를 불러오는데 실패했습니다.`);
}
const responseData = await response.json();
if (Array.isArray(responseData)) {
setKuntaeData(responseData);
updateStatistics(responseData);
} else if (responseData.error) {
throw new Error(responseData.error);
} else {
setKuntaeData([]);
updateStatistics([]);
}
} catch (error) {
console.error('Error loading kuntae data:', error);
setKuntaeData([]);
updateStatistics([]);
showNotification('데이터를 불러오는데 실패했습니다: ' + error.message, 'error');
} finally {
setIsLoading(false);
}
};
// 통계 업데이트
const updateStatistics = (data) => {
const totalDays = data.length;
const approvedDays = data.filter(item => item.status === '승인').length;
const pendingDays = data.filter(item => item.status === '대기').length;
const rejectedDays = data.filter(item => item.status === '반려').length;
setStatistics({
totalDays,
approvedDays,
pendingDays,
rejectedDays
});
};
// 필터 변경 핸들러
const handleFilterChange = (field, value) => {
setFilters(prev => ({ ...prev, [field]: value }));
};
// 검색 실행
const handleSearch = () => {
loadKuntaeData();
};
// 유틸리티 함수들
const formatDate = (dateString) => {
if (!dateString) return '-';
const date = new Date(dateString);
return date.toLocaleDateString('ko-KR');
};
const getStatusColor = (status) => {
switch (status) {
case '승인': return 'bg-green-100 text-green-800';
case '대기': return 'bg-yellow-100 text-yellow-800';
case '반려': return 'bg-red-100 text-red-800';
default: return 'bg-gray-100 text-gray-800';
}
};
// 알림 표시 함수
const showNotification = (message, type = 'info') => {
const colors = {
info: 'bg-blue-500/90 backdrop-blur-sm',
success: 'bg-green-500/90 backdrop-blur-sm',
warning: 'bg-yellow-500/90 backdrop-blur-sm',
error: 'bg-red-500/90 backdrop-blur-sm'
};
const notification = document.createElement('div');
notification.className = `fixed top-4 right-4 ${colors[type]} text-white px-4 py-3 rounded-lg z-50 transition-all duration-300 transform translate-x-0 opacity-100 shadow-lg border border-white/20`;
notification.innerHTML = `
<div class="flex items-center">
<span class="ml-2">${message}</span>
</div>
`;
notification.style.transform = 'translateX(100%)';
notification.style.opacity = '0';
document.body.appendChild(notification);
setTimeout(() => {
notification.style.transform = 'translateX(0)';
notification.style.opacity = '1';
}, 10);
setTimeout(() => {
notification.style.transform = 'translateX(100%)';
notification.style.opacity = '0';
setTimeout(() => notification.remove(), 300);
}, 3000);
};
return (
<div className="container mx-auto px-4 py-8">
{/* 개발중 경고 메시지 */}
<div className="bg-orange-500 rounded-lg p-4 mb-6 border-l-4 border-orange-700 animate-slide-up shadow-lg">
<div className="flex items-center">
<svg className="w-5 h-5 text-orange-900 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path>
</svg>
<div>
<p className="text-white font-bold text-base">🚧 개발중인 기능입니다</p>
<p className="text-orange-100 text-sm font-medium">일부 기능이 정상적으로 동작하지 않을 있습니다.</p>
</div>
</div>
</div>
{/* 검색 및 필터 섹션 */}
<div className="glass-effect rounded-lg p-6 mb-6 animate-slide-up">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label className="block text-sm font-medium text-white/80 mb-2">시작일</label>
<input
type="date"
value={filters.startDate}
onChange={(e) => handleFilterChange('startDate', e.target.value)}
className="w-full px-3 py-2 bg-white/20 border border-white/30 rounded-md text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/50 focus:border-transparent"
/>
</div>
<div>
<label className="block text-sm font-medium text-white/80 mb-2">종료일</label>
<input
type="date"
value={filters.endDate}
onChange={(e) => handleFilterChange('endDate', e.target.value)}
className="w-full px-3 py-2 bg-white/20 border border-white/30 rounded-md text-white placeholder-white/60 focus:outline-none focus:ring-2 focus:ring-white/50 focus:border-transparent"
/>
</div>
<div className="flex items-end">
<button
onClick={handleSearch}
disabled={isLoading}
className="w-full glass-effect text-white px-4 py-2 rounded-md hover:bg-white/30 transition-colors duration-200 flex items-center justify-center disabled:opacity-50"
>
{isLoading ? (
<>
<div className="loading inline-block w-4 h-4 border-2 border-white/30 border-t-white rounded-full animate-spin mr-2"></div>
로딩중...
</>
) : (
'조회'
)}
</button>
</div>
</div>
</div>
{/* 통계 카드 */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-6 mb-6 animate-slide-up">
<div className="glass-effect rounded-lg p-6 card-hover">
<div className="flex items-center">
<div className="p-3 bg-primary-500/20 rounded-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
</div>
<div className="ml-4">
<p className="text-sm font-medium text-white/80"> 신청건</p>
<p className="text-2xl font-bold text-white">{statistics.totalDays}</p>
</div>
</div>
</div>
<div className="glass-effect rounded-lg p-6 card-hover">
<div className="flex items-center">
<div className="p-3 bg-success-500/20 rounded-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<div className="ml-4">
<p className="text-sm font-medium text-white/80">승인</p>
<p className="text-2xl font-bold text-green-300">{statistics.approvedDays}</p>
</div>
</div>
</div>
<div className="glass-effect rounded-lg p-6 card-hover">
<div className="flex items-center">
<div className="p-3 bg-warning-500/20 rounded-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
</div>
<div className="ml-4">
<p className="text-sm font-medium text-white/80">대기</p>
<p className="text-2xl font-bold text-yellow-300">{statistics.pendingDays}</p>
</div>
</div>
</div>
<div className="glass-effect rounded-lg p-6 card-hover">
<div className="flex items-center">
<div className="p-3 bg-red-500/20 rounded-lg">
<svg className="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</div>
<div className="ml-4">
<p className="text-sm font-medium text-white/80">반려</p>
<p className="text-2xl font-bold text-red-300">{statistics.rejectedDays}</p>
</div>
</div>
</div>
</div>
{/* 데이터 테이블 */}
<div className="glass-effect rounded-lg overflow-hidden animate-slide-up">
<div className="table-container custom-scrollbar" style={{ maxHeight: '600px', overflowY: 'auto' }}>
<table className="min-w-full divide-y divide-white/20">
<thead className="bg-white/10 sticky top-0">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">신청일</th>
<th className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">시작일</th>
<th className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">종료일</th>
<th className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">휴가종류</th>
<th className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">일수</th>
<th className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">상태</th>
<th className="px-6 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider">사유</th>
</tr>
</thead>
<tbody className="divide-y divide-white/10">
{isLoading ? (
<tr>
<td colSpan="7" className="p-8 text-center">
<div className="inline-flex items-center">
<div className="loading inline-block w-5 h-5 border-3 border-white/30 border-t-white rounded-full animate-spin mr-3"></div>
<span className="text-white/80">데이터를 불러오는 ...</span>
</div>
</td>
</tr>
) : kuntaeData.length === 0 ? (
<tr>
<td colSpan="7" className="p-8 text-center">
<svg className="w-12 h-12 text-white/60 mx-auto mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
<p className="text-white/70">근태 데이터가 없습니다.</p>
</td>
</tr>
) : (
kuntaeData.map((item, index) => (
<tr key={item.idx || index} className="hover:bg-white/10 transition-colors">
<td className="px-6 py-4 whitespace-nowrap text-sm text-white">
{formatDate(item.requestDate)}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-white">
{formatDate(item.startDate)}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-white">
{formatDate(item.endDate)}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-white">
{item.type || '-'}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-white">
{item.days || '0'}
</td>
<td className="px-6 py-4 whitespace-nowrap">
<span className={`inline-flex px-2 py-1 text-xs font-semibold rounded-full ${getStatusColor(item.status)}`}>
{item.status || '-'}
</span>
</td>
<td className="px-6 py-4 text-sm text-white">
<div className="max-w-xs truncate" title={item.reason || ''}>
{item.reason || '-'}
</div>
</td>
</tr>
))
)}
</tbody>
</table>
</div>
</div>
</div>
);
}

View File

@@ -1,308 +0,0 @@
// LoginApp.jsx - React Login Component for GroupWare
const { useState, useEffect, useRef } = React;
function LoginApp() {
const [formData, setFormData] = useState({
gcode: '',
userId: '',
password: '',
rememberMe: false
});
const [userGroups, setUserGroups] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [message, setMessage] = useState({ type: '', text: '', show: false });
const [isFormReady, setIsFormReady] = useState(false);
const gcodeRef = useRef(null);
const userIdRef = useRef(null);
const passwordRef = useRef(null);
// 메시지 표시 함수
const showMessage = (type, text) => {
setMessage({ type, text, show: true });
setTimeout(() => {
setMessage(prev => ({ ...prev, show: false }));
}, 3000);
};
// 폼 데이터 업데이트
const handleInputChange = (e) => {
const { name, value, type, checked } = e.target;
setFormData(prev => ({
...prev,
[name]: type === 'checkbox' ? checked : value
}));
};
// 사용자 그룹 목록 로드
const loadUserGroups = async () => {
try {
const response = await fetch('/DashBoard/GetUserGroups');
const data = await response.json();
// 유효한 그룹만 필터링
const validGroups = data.filter(group => group.gcode && group.name);
setUserGroups(validGroups);
// 이전 로그인 정보 로드
await loadPreviousLoginInfo();
} catch (error) {
console.error('그룹 목록 로드 중 오류 발생:', error);
showMessage('error', '부서 목록을 불러오는 중 오류가 발생했습니다.');
}
};
// 이전 로그인 정보 로드
const loadPreviousLoginInfo = async () => {
try {
const response = await fetch('/Home/GetPreviousLoginInfo');
const result = await response.json();
if (result.Success && result.Data) {
const { Gcode, UserId } = result.Data;
setFormData(prev => ({
...prev,
gcode: Gcode || '',
userId: UserId ? UserId.split(';')[0] : ''
}));
// 포커스 설정
setTimeout(() => {
if (Gcode && UserId) {
passwordRef.current?.focus();
} else {
gcodeRef.current?.focus();
}
}, 100);
}
setIsFormReady(true);
} catch (error) {
console.error('이전 로그인 정보 로드 중 오류 발생:', error);
setIsFormReady(true);
setTimeout(() => {
gcodeRef.current?.focus();
}, 100);
}
};
// 로그인 처리
const handleLogin = async (e) => {
e.preventDefault();
const { gcode, userId, password, rememberMe } = formData;
// 유효성 검사
if (!gcode || !userId || !password) {
showMessage('error', '그룹코드/사용자ID/비밀번호를 입력해주세요.');
return;
}
setIsLoading(true);
try {
const response = await fetch('/Home/Login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
Gcode: gcode,
UserId: userId,
Password: password,
RememberMe: rememberMe
})
});
const data = await response.json();
if (data.Success) {
// 로그인 성공
showMessage('success', data.Message);
// WebView2에 로그인 성공 메시지 전송
if (window.chrome && window.chrome.webview) {
window.chrome.webview.postMessage('LOGIN_SUCCESS');
}
// 리다이렉트 URL이 있으면 이동
if (data.RedirectUrl) {
setTimeout(() => {
window.location.href = data.RedirectUrl;
}, 1000);
}
} else {
// 로그인 실패
showMessage('error', data.Message || '로그인에 실패했습니다.');
}
} catch (error) {
console.error('로그인 요청 중 오류 발생:', error);
showMessage('error', '서버 연결에 실패했습니다. 다시 시도해주세요.');
} finally {
setIsLoading(false);
}
};
// 컴포넌트 마운트 시 실행
useEffect(() => {
loadUserGroups();
}, []);
return (
<div className="gradient-bg min-h-screen flex items-center justify-center p-4">
<div className="w-full max-w-md">
{/* 로그인 카드 */}
<div className="glass-effect rounded-3xl p-8 card-hover animate-bounce-in">
{/* 로고 및 제목 */}
<div className="text-center mb-8 animate-fade-in">
<div className="w-16 h-16 bg-white/20 rounded-full flex items-center justify-center mx-auto mb-4">
<svg className="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"></path>
</svg>
</div>
<h1 className="text-2xl font-bold text-white mb-2">GroupWare</h1>
<p className="text-white/70 text-sm">로그인하여 시스템에 접속하세요</p>
</div>
{/* 로그인 폼 */}
<form onSubmit={handleLogin} className="space-y-6 animate-slide-up">
{/* Gcode 드롭다운 */}
<div className="relative">
<select
ref={gcodeRef}
name="gcode"
value={formData.gcode}
onChange={handleInputChange}
className="input-field w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl text-white focus:outline-none focus:border-primary-400 input-focus appearance-none"
required
disabled={!isFormReady}
>
<option value="" className="text-gray-800">부서를 선택하세요</option>
{userGroups.map(group => (
<option key={group.gcode} value={group.gcode} className="text-gray-800">
{group.name}
</option>
))}
</select>
<div className="absolute right-3 top-3 pointer-events-none">
<svg className="w-5 h-5 text-white/40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 9l-7 7-7-7"></path>
</svg>
</div>
</div>
{/* 사용자 ID 입력 */}
<div className="relative">
<input
ref={userIdRef}
type="text"
name="userId"
value={formData.userId}
onChange={handleInputChange}
className="input-field w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl text-white placeholder-white/60 focus:outline-none focus:border-primary-400 input-focus"
placeholder="사원번호"
required
disabled={!isFormReady}
/>
<div className="absolute right-3 top-3">
<svg className="w-5 h-5 text-white/40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path>
</svg>
</div>
</div>
{/* 비밀번호 입력 */}
<div className="relative">
<input
ref={passwordRef}
type="password"
name="password"
value={formData.password}
onChange={handleInputChange}
className="input-field w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl text-white placeholder-white/60 focus:outline-none focus:border-primary-400 input-focus"
placeholder="비밀번호"
required
disabled={!isFormReady}
/>
<div className="absolute right-3 top-3">
<svg className="w-5 h-5 text-white/40" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"></path>
</svg>
</div>
</div>
{/* 로그인 버튼 */}
<button
type="submit"
disabled={isLoading || !isFormReady}
className="w-full bg-primary-500 hover:bg-primary-600 disabled:opacity-50 disabled:cursor-not-allowed text-white font-semibold py-3 px-4 rounded-xl transition-all duration-300 transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-primary-400 focus:ring-offset-2 focus:ring-offset-transparent"
>
<span className="flex items-center justify-center">
{isLoading ? (
<>
<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-white mr-2"></div>
로그인 ...
</>
) : (
<>
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1"></path>
</svg>
로그인
</>
)}
</span>
</button>
</form>
{/* 추가 옵션 */}
<div className="mt-6 text-center">
<div className="flex items-center justify-center space-x-4 text-sm">
<label className="flex items-center text-white/70 hover:text-white cursor-pointer transition-colors">
<input
type="checkbox"
name="rememberMe"
checked={formData.rememberMe}
onChange={handleInputChange}
className="mr-2 w-4 h-4 text-primary-500 bg-white/10 border-white/20 rounded focus:ring-primary-400 focus:ring-2"
/>
로그인 정보 저장
</label>
<a href="#" className="text-primary-300 hover:text-primary-200 transition-colors">비밀번호 찾기</a>
</div>
</div>
</div>
{/* 푸터 */}
<div className="text-center mt-6 animate-fade-in">
<p className="text-white/50 text-sm">
© 2024 GroupWare System. All rights reserved.
</p>
</div>
{/* 메시지 표시 */}
{message.show && (
<div className={`fixed top-4 left-1/2 transform -translate-x-1/2 px-6 py-3 rounded-lg shadow-lg animate-slide-up ${
message.type === 'error' ? 'bg-red-500' : 'bg-green-500'
} text-white`}>
<div className="flex items-center">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
{message.type === 'error' ? (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
) : (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M5 13l4 4L19 7"></path>
)}
</svg>
<span>{message.text}</span>
</div>
</div>
)}
</div>
</div>
);
}

View File

@@ -1,884 +0,0 @@
const { useState, useEffect } = React;
function Project() {
// 상태 관리
const [projects, setProjects] = useState([]);
const [filteredProjects, setFilteredProjects] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [currentUser, setCurrentUser] = useState('사용자');
const [currentPage, setCurrentPage] = useState(1);
const [itemsPerPage] = useState(10);
// 모달 상태
const [showProjectModal, setShowProjectModal] = useState(false);
const [showDeleteModal, setShowDeleteModal] = useState(false);
const [currentProjectIdx, setCurrentProjectIdx] = useState(null);
// 필터 상태
const [filters, setFilters] = useState({
status: '진행',
search: '',
manager: 'my'
});
// UI 상태
const [showFilters, setShowFilters] = useState(false);
const [showColumnDropdown, setShowColumnDropdown] = useState(false);
const [visibleColumns, setVisibleColumns] = useState({
serial: false,
plant: false,
line: false,
package: false,
staff: false,
process: false,
expire: false,
delivery: false,
design: false,
electric: false,
program: false,
budgetDue: false,
budget: false,
jasmin: false
});
// 프로젝트 폼 상태
const [projectForm, setProjectForm] = useState({
idx: 0,
name: '',
process: '',
sdate: '',
edate: '',
ddate: '',
odate: '',
userManager: '',
status: '진행',
memo: ''
});
// 통계 상태
const [statusCounts, setStatusCounts] = useState({
진행: 0,
완료: 0,
대기: 0,
중단: 0
});
// 컴포넌트 마운트시 초기화
useEffect(() => {
getCurrentUser();
loadProjects();
}, []);
// 필터 변경시 프로젝트 목록 새로 로드
useEffect(() => {
loadProjects();
}, [filters.status, filters.manager]);
// 검색어 변경시 필터링
useEffect(() => {
filterData();
}, [filters.search, projects]);
// 현재 사용자 정보 가져오기
const getCurrentUser = async () => {
try {
const response = await fetch('/Common/GetCurrentUser');
const data = await response.json();
if (data.Success && data.Data) {
const userName = data.Data.userName || data.Data.name || '사용자';
setCurrentUser(userName);
}
} catch (error) {
console.error('Error getting current user:', error);
}
};
// 프로젝트 목록 로드
const loadProjects = async () => {
setIsLoading(true);
try {
const response = await fetch(`/Project/GetProjects?status=${filters.status}&userFilter=${filters.manager}`);
const data = await response.json();
if (data.Success) {
const projectData = data.Data || [];
setProjects(projectData);
setFilteredProjects(projectData);
updateStatusCounts(projectData);
if (data.CurrentUser) {
setCurrentUser(data.CurrentUser);
}
} else {
console.error('Error:', data.Message);
showNotification('데이터를 불러오는데 실패했습니다.', 'error');
}
} catch (error) {
console.error('Error:', error);
showNotification('데이터를 불러오는데 실패했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 상태별 카운트 업데이트
const updateStatusCounts = (projectData) => {
const counts = { 진행: 0, 완료: 0, 대기: 0, 중단: 0 };
projectData.forEach(project => {
const status = project.상태 || '진행';
counts[status] = (counts[status] || 0) + 1;
});
setStatusCounts(counts);
};
// 데이터 필터링
const filterData = () => {
if (!filters.search.trim()) {
setFilteredProjects(projects);
setCurrentPage(1);
return;
}
const searchTerm = filters.search.toLowerCase();
const filtered = projects.filter(project => {
return (project.프로젝트명 && project.프로젝트명.toLowerCase().includes(searchTerm)) ||
(project.프로젝트공정 && project.프로젝트공정.toLowerCase().includes(searchTerm)) ||
(project.자산번호 && project.자산번호.toLowerCase().includes(searchTerm)) ||
(project.장비모델 && project.장비모델.toLowerCase().includes(searchTerm)) ||
(project.시리얼번호 && project.시리얼번호.toLowerCase().includes(searchTerm)) ||
(project.프로젝트관리자 && project.프로젝트관리자.toLowerCase().includes(searchTerm)) ||
(project.설계담당 && project.설계담당.toLowerCase().includes(searchTerm)) ||
(project.전장담당 && project.전장담당.toLowerCase().includes(searchTerm)) ||
(project.프로그램담당 && project.프로그램담당.toLowerCase().includes(searchTerm));
});
setFilteredProjects(filtered);
setCurrentPage(1);
};
// 프로젝트 추가 모달 표시
const showAddProjectModal = () => {
setCurrentProjectIdx(null);
setProjectForm({
idx: 0,
name: '',
process: '',
sdate: '',
edate: '',
ddate: '',
odate: '',
userManager: '',
status: '진행',
memo: ''
});
setShowProjectModal(true);
};
// 프로젝트 편집
const editProject = async (idx) => {
setCurrentProjectIdx(idx);
setIsLoading(true);
try {
const response = await fetch(`/Project/GetProject?id=${idx}`);
const data = await response.json();
if (data.Success && data.Data) {
const project = data.Data;
setProjectForm({
idx: project.idx,
name: project.프로젝트명 || '',
process: project.프로젝트공정 || '',
sdate: project.시작일 || '',
edate: project.완료일 || '',
ddate: project.만료일 || '',
odate: project.출고일 || '',
userManager: project.프로젝트관리자 || '',
status: project.상태 || '진행',
memo: project.memo || ''
});
setShowProjectModal(true);
} else {
showNotification('프로젝트 정보를 불러오는데 실패했습니다: ' + data.Message, 'error');
}
} catch (error) {
console.error('Error:', error);
showNotification('프로젝트 정보를 불러오는데 실패했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 프로젝트 저장 (추가/수정)
const saveProject = async (e) => {
e.preventDefault();
setIsLoading(true);
const projectData = {
...projectForm,
idx: currentProjectIdx ? parseInt(projectForm.idx) : 0,
sdate: projectForm.sdate || null,
edate: projectForm.edate || null,
ddate: projectForm.ddate || null,
odate: projectForm.odate || null
};
const url = currentProjectIdx ? '/Project/UpdateProject' : '/Project/CreateProject';
const method = currentProjectIdx ? 'PUT' : 'POST';
try {
const response = await fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(projectData)
});
const data = await response.json();
if (data.Success) {
showNotification(data.Message || (currentProjectIdx ? '프로젝트가 수정되었습니다.' : '프로젝트가 추가되었습니다.'), 'success');
setShowProjectModal(false);
loadProjects();
} else {
showNotification('오류: ' + data.Message, 'error');
}
} catch (error) {
console.error('Error:', error);
showNotification('저장 중 오류가 발생했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 프로젝트 삭제
const deleteProject = async () => {
if (!currentProjectIdx) return;
setIsLoading(true);
try {
const response = await fetch(`/Project/DeleteProject?id=${currentProjectIdx}`, {
method: 'DELETE'
});
const data = await response.json();
if (data.Success) {
showNotification(data.Message || '프로젝트가 삭제되었습니다.', 'success');
setShowDeleteModal(false);
setShowProjectModal(false);
loadProjects();
} else {
showNotification('오류: ' + data.Message, 'error');
}
} catch (error) {
console.error('Error:', error);
showNotification('삭제 중 오류가 발생했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 필터 초기화
const clearFilters = () => {
setFilters({
status: '진행',
search: '',
manager: 'my'
});
};
// 엑셀 다운로드
const exportToExcel = () => {
if (filteredProjects.length === 0) {
showNotification('내보낼 데이터가 없습니다.', 'warning');
return;
}
const headers = ['상태', '자산번호', '장비모델', '시리얼번호', '우선순위', '요청국가', '요청공장', '요청라인', '요청부서패키지', '요청자', '프로젝트공정', '시작일', '완료일', '만료일', '출고일', '프로젝트명', '프로젝트관리자', '설계담당', '전장담당', '프로그램담당', '예산만기일', '예산', '웹관리번호'];
const csvContent = [
headers.join(','),
...filteredProjects.map(project => [
project.상태 || '',
project.자산번호 || '',
project.장비모델 || '',
project.시리얼번호 || '',
project.우선순위 || '',
project.요청국가 || '',
project.요청공장 || '',
project.요청라인 || '',
project.요청부서패키지 || '',
project.요청자 || '',
project.프로젝트공정 || '',
project.시작일 || '',
project.완료일 || '',
project.만료일 || '',
project.출고일 || '',
project.프로젝트명 || '',
project.프로젝트관리자 || '',
project.설계담당 || '',
project.전장담당 || '',
project.프로그램담당 || '',
project.예산만기일 || '',
project.예산 || '',
project.웹관리번호 || ''
].join(','))
].join('\n');
const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', `프로젝트목록_${new Date().toISOString().split('T')[0]}.csv`);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
// 유틸리티 함수들
const getStatusClass = (status) => {
switch(status) {
case '진행': return 'bg-blue-500/20 text-blue-300';
case '완료': return 'bg-green-500/20 text-green-300';
case '대기': return 'bg-yellow-500/20 text-yellow-300';
case '중단': return 'bg-red-500/20 text-red-300';
default: return 'bg-gray-500/20 text-gray-300';
}
};
const formatDateToMonthDay = (dateString) => {
if (!dateString) return '';
try {
const date = new Date(dateString);
if (isNaN(date.getTime())) return dateString;
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${month}-${day}`;
} catch (error) {
return dateString;
}
};
// 알림 표시 함수
const showNotification = (message, type = 'info') => {
const colors = {
info: 'bg-blue-500/90 backdrop-blur-sm',
success: 'bg-green-500/90 backdrop-blur-sm',
warning: 'bg-yellow-500/90 backdrop-blur-sm',
error: 'bg-red-500/90 backdrop-blur-sm'
};
const notification = document.createElement('div');
notification.className = `fixed top-4 right-4 ${colors[type]} text-white px-4 py-3 rounded-lg z-50 transition-all duration-300 transform translate-x-0 opacity-100 shadow-lg border border-white/20`;
notification.innerHTML = `
<div class="flex items-center">
<span class="ml-2">${message}</span>
</div>
`;
notification.style.transform = 'translateX(100%)';
notification.style.opacity = '0';
document.body.appendChild(notification);
setTimeout(() => {
notification.style.transform = 'translateX(0)';
notification.style.opacity = '1';
}, 10);
setTimeout(() => {
notification.style.transform = 'translateX(100%)';
notification.style.opacity = '0';
setTimeout(() => notification.remove(), 300);
}, 3000);
};
// 페이지네이션 계산
const totalPages = Math.ceil(filteredProjects.length / itemsPerPage);
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const paginatedProjects = filteredProjects.slice(startIndex, endIndex);
const changePage = (page) => {
if (page >= 1 && page <= totalPages) {
setCurrentPage(page);
}
};
return (
<div className="container mx-auto px-4 py-8">
{/* 프로젝트 목록 */}
<div className="glass-effect rounded-lg overflow-hidden animate-slide-up">
<div className="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 className="text-xl font-semibold text-white flex items-center">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path>
</svg>
프로젝트 목록
</h2>
<div className="flex space-x-3">
<button onClick={showAddProjectModal} className="bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg transition-colors flex items-center text-sm" title="프로젝트 추가">
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
</svg>
프로젝트 추가
</button>
<button onClick={() => setShowFilters(!showFilters)} className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors flex items-center text-sm" title="필터 표시/숨김">
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707L13 14v6a1 1 0 01-.707.293l-4-1A1 1 0 018 19v-5L0.293 7.293A1 1 0 010 6.586V4z"></path>
</svg>
필터
<svg className={`w-4 h-4 ml-2 transition-transform ${showFilters ? 'rotate-180' : ''}`} fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 9l-7 7-7-7"></path>
</svg>
</button>
</div>
</div>
{/* 상태별 카드 */}
<div className="grid grid-cols-1 md:grid-cols-4 gap-4 p-4 border-b border-white/10">
<div className="bg-white/10 rounded-lg p-4 text-center">
<div className="text-2xl font-bold text-blue-300 mb-1">{statusCounts.진행}</div>
<div className="text-sm text-white/60">진행</div>
</div>
<div className="bg-white/10 rounded-lg p-4 text-center">
<div className="text-2xl font-bold text-green-300 mb-1">{statusCounts.완료}</div>
<div className="text-sm text-white/60">완료</div>
</div>
<div className="bg-white/10 rounded-lg p-4 text-center">
<div className="text-2xl font-bold text-yellow-300 mb-1">{statusCounts.대기}</div>
<div className="text-sm text-white/60">대기</div>
</div>
<div className="bg-white/10 rounded-lg p-4 text-center">
<div className="text-2xl font-bold text-red-300 mb-1">{statusCounts.중단}</div>
<div className="text-sm text-white/60">중단</div>
</div>
</div>
{/* 필터 영역 */}
{showFilters && (
<div className="p-4 border-b border-white/10 animate-slide-up">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
{/* 좌측: 필터 컨트롤 */}
<div className="lg:col-span-2 space-y-3">
<div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
<div>
<label className="block text-xs font-medium text-white/80 mb-1">상태</label>
<select
value={filters.status}
onChange={(e) => setFilters({...filters, status: e.target.value})}
className="w-full bg-white/20 border border-white/30 rounded-md px-2 py-1 text-white focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent text-xs"
>
<option value="진행">진행</option>
<option value="완료">완료</option>
<option value="대기">대기</option>
<option value="중단">중단</option>
</select>
</div>
<div>
<label className="block text-xs font-medium text-white/80 mb-1">검색</label>
<input
type="text"
value={filters.search}
onChange={(e) => setFilters({...filters, search: e.target.value})}
placeholder="프로젝트명 검색..."
className="w-full bg-white/20 border border-white/30 rounded-md px-2 py-1 text-white placeholder-white/60 focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent text-xs"
/>
</div>
<div>
<label className="block text-xs font-medium text-white/80 mb-1">담당자</label>
<select
value={filters.manager}
onChange={(e) => setFilters({...filters, manager: e.target.value})}
className="w-full bg-white/20 border border-white/30 rounded-md px-2 py-1 text-white focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent text-xs"
>
<option value="my"> 프로젝트</option>
<option value="all">전체 프로젝트</option>
</select>
</div>
</div>
</div>
{/* 우측: 액션 버튼들 */}
<div className="flex flex-wrap gap-2 justify-end">
<div className="relative">
<button onClick={() => setShowColumnDropdown(!showColumnDropdown)} className="bg-purple-500 hover:bg-purple-600 text-white px-4 py-2 rounded-lg flex items-center transition-colors text-sm" title="컬럼 표시/숨김">
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2H9z"></path>
</svg>
컬럼 설정
</button>
{showColumnDropdown && (
<div className="absolute top-full right-0 bg-gray-800/95 backdrop-blur-sm border border-white/20 rounded-lg p-3 min-w-48 z-50 mt-1">
<div className="text-sm font-medium text-white/80 mb-2">표시할 컬럼 선택</div>
<div className="space-y-1 text-sm max-h-40 overflow-y-auto">
{Object.entries({
serial: '시리얼번호',
plant: '요청공장',
line: '요청라인',
package: '요청부서패키지',
staff: '요청자',
process: '프로젝트공정',
expire: '만료일',
delivery: '출고일',
design: '설계담당',
electric: '전장담당',
program: '프로그램담당',
budgetDue: '예산만기일',
budget: '예산',
jasmin: '웹관리번호'
}).map(([key, label]) => (
<label key={key} className="flex items-center text-white cursor-pointer hover:text-blue-300">
<input
type="checkbox"
checked={visibleColumns[key]}
onChange={(e) => setVisibleColumns({...visibleColumns, [key]: e.target.checked})}
className="mr-2"
/>
{label}
</label>
))}
</div>
</div>
)}
</div>
<button onClick={exportToExcel} className="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-lg flex items-center transition-colors text-sm" title="엑셀 다운로드">
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
엑셀 다운로드
</button>
<button onClick={clearFilters} className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg flex items-center transition-colors text-sm" title="필터 초기화">
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
</svg>
필터 초기화
</button>
</div>
</div>
</div>
)}
{/* 데이터 테이블 */}
<div className="px-4 py-3 bg-white/5">
<div className="text-sm text-white/70 font-medium">프로젝트 현황</div>
</div>
<div className="overflow-x-auto custom-scrollbar">
<table className="w-full divide-y divide-white/20">
<thead className="bg-white/10">
<tr>
<th className="px-4 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-20">상태</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 min-w-32">프로젝트명</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-24">자산번호</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-28">장비모델</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-24">우선순위</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-20">요청국가</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-28">프로젝트관리자</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-24">시작일</th>
<th className="px-4 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-24">완료일</th>
{visibleColumns.serial && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-24">시리얼번호</th>}
{visibleColumns.plant && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-20">요청공장</th>}
{visibleColumns.line && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-20">요청라인</th>}
{visibleColumns.package && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-28">요청부서패키지</th>}
{visibleColumns.staff && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-20">요청자</th>}
{visibleColumns.process && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-24">프로젝트공정</th>}
{visibleColumns.expire && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-24">만료일</th>}
{visibleColumns.delivery && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-24">출고일</th>}
{visibleColumns.design && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-24">설계담당</th>}
{visibleColumns.electric && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-24">전장담당</th>}
{visibleColumns.program && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-24">프로그램담당</th>}
{visibleColumns.budgetDue && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-24">예산만기일</th>}
{visibleColumns.budget && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider border-r border-white/20 w-20">예산</th>}
{visibleColumns.jasmin && <th className="px-3 py-3 text-left text-xs font-medium text-white/80 uppercase tracking-wider w-24">웹관리번호</th>}
</tr>
</thead>
<tbody className="divide-y divide-white/10">
{isLoading ? (
<tr>
<td colSpan="23" className="px-6 py-4 text-center">
<div className="inline-flex items-center">
<div className="loading inline-block w-5 h-5 border-3 border-white/30 border-t-white rounded-full animate-spin mr-3"></div>
<span className="text-white/80">데이터를 불러오는 ...</span>
</div>
</td>
</tr>
) : paginatedProjects.length === 0 ? (
<tr>
<td colSpan="23" className="px-6 py-4 text-center text-white/60">데이터가 없습니다.</td>
</tr>
) : (
paginatedProjects.map(project => (
<tr key={project.idx} onClick={() => editProject(project.idx)} className="hover:bg-white/10 cursor-pointer transition-colors">
<td className="px-4 py-4 text-sm border-r border-white/20">
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusClass(project.상태)}`}>
{project.상태 || '진행'}
</span>
</td>
<td className="px-4 py-4 text-sm border-r border-white/20 font-medium">{project.프로젝트명 || ''}</td>
<td className="px-4 py-4 text-sm border-r border-white/20">{project.자산번호 || ''}</td>
<td className="px-4 py-4 text-sm border-r border-white/20">{project.장비모델 || ''}</td>
<td className="px-4 py-4 text-sm border-r border-white/20">{project.우선순위 || ''}</td>
<td className="px-4 py-4 text-sm border-r border-white/20">{project.요청국가 || ''}</td>
<td className="px-4 py-4 text-sm border-r border-white/20">{project.프로젝트관리자 || ''}</td>
<td className="px-4 py-4 text-sm border-r border-white/20">{formatDateToMonthDay(project.시작일)}</td>
<td className="px-4 py-4 text-sm border-r border-white/20">{formatDateToMonthDay(project.완료일)}</td>
{visibleColumns.serial && <td className="px-3 py-4 text-sm border-r border-white/20">{project.시리얼번호 || ''}</td>}
{visibleColumns.plant && <td className="px-3 py-4 text-sm border-r border-white/20">{project.요청공장 || ''}</td>}
{visibleColumns.line && <td className="px-3 py-4 text-sm border-r border-white/20">{project.요청라인 || ''}</td>}
{visibleColumns.package && <td className="px-3 py-4 text-sm border-r border-white/20">{project.요청부서패키지 || ''}</td>}
{visibleColumns.staff && <td className="px-3 py-4 text-sm border-r border-white/20">{project.요청자 || ''}</td>}
{visibleColumns.process && <td className="px-3 py-4 text-sm border-r border-white/20">{project.프로젝트공정 || ''}</td>}
{visibleColumns.expire && <td className="px-3 py-4 text-sm border-r border-white/20">{formatDateToMonthDay(project.만료일)}</td>}
{visibleColumns.delivery && <td className="px-3 py-4 text-sm border-r border-white/20">{formatDateToMonthDay(project.출고일)}</td>}
{visibleColumns.design && <td className="px-3 py-4 text-sm border-r border-white/20">{project.설계담당 || ''}</td>}
{visibleColumns.electric && <td className="px-3 py-4 text-sm border-r border-white/20">{project.전장담당 || ''}</td>}
{visibleColumns.program && <td className="px-3 py-4 text-sm border-r border-white/20">{project.프로그램담당 || ''}</td>}
{visibleColumns.budgetDue && <td className="px-3 py-4 text-sm border-r border-white/20">{formatDateToMonthDay(project.예산만기일)}</td>}
{visibleColumns.budget && <td className="px-3 py-4 text-sm border-r border-white/20">{project.예산 || ''}</td>}
{visibleColumns.jasmin && (
<td className="px-3 py-4 text-sm">
{project.웹관리번호 ? (
<a href={`https://scwa.amkor.co.kr/jasmine/view/${project.웹관리번호}`} target="_blank" rel="noopener noreferrer" className="text-blue-300 hover:text-blue-200 underline">
{project.웹관리번호}
</a>
) : ''}
</td>
)}
</tr>
))
)}
</tbody>
</table>
</div>
{/* 페이징 */}
<div className="px-4 py-4 border-t border-white/10">
<div className="flex items-center justify-between">
<div className="text-sm text-white/60">
{filteredProjects.length} {startIndex + 1}-{Math.min(endIndex, filteredProjects.length)} 표시
</div>
<div className="flex items-center space-x-2">
<button onClick={() => changePage(currentPage - 1)} disabled={currentPage <= 1} className="px-3 py-1 bg-white/20 hover:bg-white/30 text-white rounded-md text-sm disabled:opacity-50 disabled:cursor-not-allowed">
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 19l-7-7 7-7"></path>
</svg>
</button>
<div className="flex space-x-1">
{Array.from({length: Math.min(5, totalPages)}, (_, i) => {
const pageNum = Math.max(1, currentPage - 2) + i;
if (pageNum > totalPages) return null;
return (
<button
key={pageNum}
onClick={() => changePage(pageNum)}
className={`px-3 py-1 rounded-md text-sm transition-colors ${
pageNum === currentPage
? 'bg-primary-500 text-white'
: 'bg-white/20 hover:bg-white/30 text-white'
}`}
>
{pageNum}
</button>
);
})}
</div>
<button onClick={() => changePage(currentPage + 1)} disabled={currentPage >= totalPages} className="px-3 py-1 bg-white/20 hover:bg-white/30 text-white rounded-md text-sm disabled:opacity-50 disabled:cursor-not-allowed">
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 5l7 7-7 7"></path>
</svg>
</button>
</div>
</div>
</div>
</div>
{/* 프로젝트 추가/편집 모달 */}
{showProjectModal && (
<div className="fixed inset-0 bg-black bg-opacity-50 z-50">
<div className="flex items-center justify-center min-h-screen p-4">
<div className="glass-effect rounded-lg w-full max-w-2xl animate-slide-up">
<div className="p-6">
<div className="flex justify-between items-center mb-6">
<h3 className="text-xl font-semibold">{currentProjectIdx ? '프로젝트 편집' : '프로젝트 추가'}</h3>
<button onClick={() => setShowProjectModal(false)} className="text-white/60 hover:text-white">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
<form onSubmit={saveProject}>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div>
<label className="block text-sm font-medium text-white/80 mb-2">프로젝트명 *</label>
<input
type="text"
value={projectForm.name}
onChange={(e) => setProjectForm({...projectForm, name: e.target.value})}
required
className="w-full bg-white/20 border border-white/30 rounded-md px-3 py-2 text-white placeholder-white/60 focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent"
/>
</div>
<div>
<label className="block text-sm font-medium text-white/80 mb-2">부서</label>
<input
type="text"
value={projectForm.process}
onChange={(e) => setProjectForm({...projectForm, process: e.target.value})}
className="w-full bg-white/20 border border-white/30 rounded-md px-3 py-2 text-white placeholder-white/60 focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent"
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div>
<label className="block text-sm font-medium text-white/80 mb-2">시작일</label>
<input
type="date"
value={projectForm.sdate}
onChange={(e) => setProjectForm({...projectForm, sdate: e.target.value})}
className="w-full bg-white/20 border border-white/30 rounded-md px-3 py-2 text-white focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent"
/>
</div>
<div>
<label className="block text-sm font-medium text-white/80 mb-2">종료일</label>
<input
type="date"
value={projectForm.edate}
onChange={(e) => setProjectForm({...projectForm, edate: e.target.value})}
className="w-full bg-white/20 border border-white/30 rounded-md px-3 py-2 text-white focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent"
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div>
<label className="block text-sm font-medium text-white/80 mb-2">개발완료일</label>
<input
type="date"
value={projectForm.ddate}
onChange={(e) => setProjectForm({...projectForm, ddate: e.target.value})}
className="w-full bg-white/20 border border-white/30 rounded-md px-3 py-2 text-white focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent"
/>
</div>
<div>
<label className="block text-sm font-medium text-white/80 mb-2">운영개시일</label>
<input
type="date"
value={projectForm.odate}
onChange={(e) => setProjectForm({...projectForm, odate: e.target.value})}
className="w-full bg-white/20 border border-white/30 rounded-md px-3 py-2 text-white focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent"
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div>
<label className="block text-sm font-medium text-white/80 mb-2">담당자</label>
<input
type="text"
value={projectForm.userManager}
onChange={(e) => setProjectForm({...projectForm, userManager: e.target.value})}
className="w-full bg-white/20 border border-white/30 rounded-md px-3 py-2 text-white placeholder-white/60 focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent"
/>
</div>
<div>
<label className="block text-sm font-medium text-white/80 mb-2">상태</label>
<select
value={projectForm.status}
onChange={(e) => setProjectForm({...projectForm, status: e.target.value})}
className="w-full bg-white/20 border border-white/30 rounded-md px-3 py-2 text-white focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent"
>
<option value="진행">진행</option>
<option value="완료">완료</option>
<option value="대기">대기</option>
<option value="중단">중단</option>
</select>
</div>
</div>
<div className="mb-4">
<label className="block text-sm font-medium text-white/80 mb-2">메모</label>
<textarea
value={projectForm.memo}
onChange={(e) => setProjectForm({...projectForm, memo: e.target.value})}
rows="3"
className="w-full bg-white/20 border border-white/30 rounded-md px-3 py-2 text-white placeholder-white/60 focus:outline-none focus:ring-1 focus:ring-white/50 focus:border-transparent"
></textarea>
</div>
<div className="flex justify-between items-center">
{currentProjectIdx && (
<button type="button" onClick={() => setShowDeleteModal(true)} className="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-md transition-colors">
삭제
</button>
)}
<div className="flex space-x-2 ml-auto">
<button type="button" onClick={() => setShowProjectModal(false)} className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-md transition-colors">
취소
</button>
<button type="submit" className="bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-md transition-colors">
저장
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
)}
{/* 삭제 확인 모달 */}
{showDeleteModal && (
<div className="fixed inset-0 bg-black bg-opacity-50 z-50">
<div className="flex items-center justify-center min-h-screen p-4">
<div className="glass-effect rounded-lg w-full max-w-md animate-slide-up">
<div className="p-6">
<div className="flex items-center mb-4">
<svg className="w-8 h-8 text-red-400 mr-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path>
</svg>
<h3 className="text-lg font-semibold">삭제 확인</h3>
</div>
<p className="text-white/80 mb-6">선택한 프로젝트를 삭제하시겠습니까?<br><span className="text-sm text-gray-500"> 작업은 되돌릴 없습니다.</span></p>
<div className="flex justify-end space-x-2">
<button onClick={() => setShowDeleteModal(false)} className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-md transition-colors">
취소
</button>
<button onClick={deleteProject} className="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-md transition-colors">
삭제
</button>
</div>
</div>
</div>
</div>
</div>
)}
{/* 로딩 인디케이터 */}
{isLoading && (
<div className="fixed top-4 right-4 bg-white/20 backdrop-blur-sm rounded-full px-4 py-2 text-white text-sm z-40">
<div className="flex items-center">
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
처리 ...
</div>
</div>
)}
{/* 외부 클릭시 드롭다운 닫기 */}
{showColumnDropdown && (
<div
className="fixed inset-0 z-10"
onClick={() => setShowColumnDropdown(false)}
></div>
)}
</div>
);
}

View File

@@ -1,147 +0,0 @@
// TestApp.jsx - React Test Component for GroupWare
const { useState, useEffect } = React;
function TestApp() {
const [status, setStatus] = useState('loading');
const [counter, setCounter] = useState(0);
const [serverTime, setServerTime] = useState('');
const [apiTest, setApiTest] = useState({ status: 'pending', message: '' });
// 컴포넌트가 마운트될 때 실행
useEffect(() => {
// React가 정상적으로 로드되었음을 표시
setTimeout(() => {
setStatus('success');
setServerTime(new Date().toLocaleString('ko-KR'));
}, 1000);
// API 테스트
testAPI();
}, []);
// GroupWare API 테스트 함수
const testAPI = async () => {
try {
// Home 컨트롤러 테스트
const response = await fetch('/Home');
if (response.ok) {
setApiTest({ status: 'success', message: 'API 연결 성공' });
} else {
setApiTest({ status: 'warning', message: `API 응답: ${response.status}` });
}
} catch (error) {
setApiTest({ status: 'error', message: `API 오류: ${error.message}` });
}
};
const buttonStyle = {
padding: '10px 20px',
margin: '5px',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
fontSize: '14px'
};
return (
<div>
<div className={`status ${status === 'success' ? 'success' : 'loading'}`}>
{status === 'success' ? (
<div>
<h3> React 컴포넌트가 성공적으로 로드되었습니다!</h3>
<p><strong>현재 시간:</strong> {serverTime}</p>
<p><strong>파일 위치:</strong> /react/TestApp.jsx</p>
</div>
) : (
<h3>React 컴포넌트를 로딩 중입니다...</h3>
)}
</div>
{status === 'success' && (
<div>
<div className="status">
<h3>📊 상태 관리 테스트</h3>
<p><strong>카운터:</strong> {counter}</p>
<button
onClick={() => setCounter(counter + 1)}
style={{
...buttonStyle,
backgroundColor: '#007bff',
color: 'white'
}}
>
증가 (+1)
</button>
<button
onClick={() => setCounter(counter - 1)}
style={{
...buttonStyle,
backgroundColor: '#dc3545',
color: 'white'
}}
>
감소 (-1)
</button>
<button
onClick={() => setCounter(0)}
style={{
...buttonStyle,
backgroundColor: '#6c757d',
color: 'white'
}}
>
리셋
</button>
</div>
<div className={`status ${
apiTest.status === 'success' ? 'success' :
apiTest.status === 'error' ? 'error' : 'loading'
}`}>
<h3>🌐 GroupWare API 연결 테스트</h3>
<p><strong>상태:</strong> {apiTest.message}</p>
<p><strong>테스트 엔드포인트:</strong> /Home</p>
<button
onClick={testAPI}
style={{
...buttonStyle,
backgroundColor: '#28a745',
color: 'white'
}}
>
API 다시 테스트
</button>
</div>
<div className="status">
<h3>📋 React + OWIN 통합 테스트 체크리스트</h3>
<ul style={{ textAlign: 'left' }}>
<li> OWIN 정적 파일 서빙</li>
<li> React 라이브러리 로딩 (CDN)</li>
<li> JSX 파일 분리 로딩</li>
<li> JSX 컴파일 (Babel)</li>
<li> React Hooks (useState, useEffect)</li>
<li> 이벤트 핸들링</li>
<li> API 호출 (fetch)</li>
<li> 반응형 UI 업데이트</li>
<li> 컴포넌트 모듈화</li>
</ul>
</div>
<div className="status success">
<h3>🎉 통합 테스트 결과</h3>
<p>GroupWare + OWIN + React 환경이 성공적으로 구성되었습니다!</p>
<p><strong>다음 단계:</strong></p>
<ul style={{ textAlign: 'left' }}>
<li>React Router 추가 (SPA 라우팅)</li>
<li>상태 관리 라이브러리 추가 (Redux/Zustand)</li>
<li>UI 컴포넌트 라이브러리 추가 (Material-UI/Ant Design)</li>
<li>번들링 도구 설정 (Webpack/Vite)</li>
<li>TypeScript 지원 추가</li>
</ul>
</div>
</div>
)}
</div>
);
}

View File

@@ -1,811 +0,0 @@
const { useState, useEffect } = React;
function Todo() {
// 상태 관리
const [todos, setTodos] = useState([]);
const [activeTodos, setActiveTodos] = useState([]);
const [completedTodos, setCompletedTodos] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [currentTab, setCurrentTab] = useState('active');
const [currentEditId, setCurrentEditId] = useState(null);
// 모달 상태
const [showAddModal, setShowAddModal] = useState(false);
const [showEditModal, setShowEditModal] = useState(false);
// 폼 상태
const [todoForm, setTodoForm] = useState({
title: '',
remark: '',
expire: '',
seqno: 0,
flag: false,
request: '',
status: '0'
});
const [editForm, setEditForm] = useState({
idx: 0,
title: '',
remark: '',
expire: '',
seqno: 0,
flag: false,
request: '',
status: '0'
});
// 컴포넌트 마운트시 할일 목록 로드
useEffect(() => {
loadTodos();
}, []);
// 할일 목록을 활성/완료로 분리
useEffect(() => {
const active = todos.filter(todo => (todo.status || '0') !== '5');
const completed = todos.filter(todo => (todo.status || '0') === '5');
setActiveTodos(active);
setCompletedTodos(completed);
}, [todos]);
// 할일 목록 로드
const loadTodos = async () => {
setIsLoading(true);
try {
const response = await fetch('/Todo/GetTodos');
const data = await response.json();
if (data.Success) {
setTodos(data.Data || []);
} else {
showNotification(data.Message || '할일 목록을 불러올 수 없습니다.', 'error');
}
} catch (error) {
console.error('할일 목록 로드 중 오류:', error);
showNotification('서버 연결에 실패했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 새 할일 추가
const addTodo = async (e) => {
e.preventDefault();
if (!todoForm.remark.trim()) {
showNotification('할일 내용을 입력해주세요.', 'error');
return;
}
setIsLoading(true);
try {
const response = await fetch('/Todo/CreateTodo', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
...todoForm,
seqno: parseInt(todoForm.seqno),
expire: todoForm.expire || null,
request: todoForm.request || null
})
});
const data = await response.json();
if (data.Success) {
setShowAddModal(false);
setTodoForm({
title: '',
remark: '',
expire: '',
seqno: 0,
flag: false,
request: '',
status: '0'
});
loadTodos();
showNotification(data.Message || '할일이 추가되었습니다.', 'success');
} else {
showNotification(data.Message || '할일 추가에 실패했습니다.', 'error');
}
} catch (error) {
console.error('할일 추가 중 오류:', error);
showNotification('서버 연결에 실패했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 할일 수정
const updateTodo = async () => {
if (!editForm.remark.trim()) {
showNotification('할일 내용을 입력해주세요.', 'error');
return;
}
setIsLoading(true);
try {
const response = await fetch('/Todo/UpdateTodo', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
...editForm,
seqno: parseInt(editForm.seqno),
expire: editForm.expire || null,
request: editForm.request || null
})
});
const data = await response.json();
if (data.Success) {
setShowEditModal(false);
setCurrentEditId(null);
loadTodos();
showNotification(data.Message || '할일이 수정되었습니다.', 'success');
} else {
showNotification(data.Message || '할일 수정에 실패했습니다.', 'error');
}
} catch (error) {
console.error('할일 수정 중 오류:', error);
showNotification('서버 연결에 실패했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 상태 업데이트 (편집 모달에서 바로 서버에 반영)
const updateTodoStatus = async (status) => {
if (!currentEditId) return;
const formData = {
...editForm,
status: status,
seqno: parseInt(editForm.seqno),
expire: editForm.expire || null,
request: editForm.request || null
};
if (!formData.remark.trim()) {
showNotification('할일 내용을 입력해주세요.', 'error');
return;
}
setIsLoading(true);
try {
const response = await fetch('/Todo/UpdateTodo', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(formData)
});
const data = await response.json();
if (data.Success) {
setShowEditModal(false);
setCurrentEditId(null);
loadTodos();
showNotification(`상태가 '${getStatusText(status)}'(으)로 변경되었습니다.`, 'success');
} else {
showNotification(data.Message || '상태 변경에 실패했습니다.', 'error');
}
} catch (error) {
console.error('상태 변경 중 오류:', error);
showNotification('서버 연결에 실패했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 할일 편집 모달 열기
const editTodo = async (id) => {
setCurrentEditId(id);
setIsLoading(true);
try {
const response = await fetch(`/Todo/GetTodo?id=${id}`);
const data = await response.json();
if (data.Success && data.Data) {
const todo = data.Data;
setEditForm({
idx: todo.idx,
title: todo.title || '',
remark: todo.remark || '',
expire: todo.expire ? new Date(todo.expire).toISOString().split('T')[0] : '',
seqno: todo.seqno || 0,
flag: todo.flag || false,
request: todo.request || '',
status: todo.status || '0'
});
setShowEditModal(true);
} else {
showNotification(data.Message || '할일 정보를 불러올 수 없습니다.', 'error');
}
} catch (error) {
console.error('할일 조회 중 오류:', error);
showNotification('서버 연결에 실패했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 할일 삭제
const deleteTodo = async (id) => {
if (!confirm('정말로 이 할일을 삭제하시겠습니까?')) {
return;
}
setIsLoading(true);
try {
const response = await fetch(`/Todo/DeleteTodo?id=${id}`, {
method: 'DELETE'
});
const data = await response.json();
if (data.Success) {
loadTodos();
showNotification(data.Message || '할일이 삭제되었습니다.', 'success');
} else {
showNotification(data.Message || '할일 삭제에 실패했습니다.', 'error');
}
} catch (error) {
console.error('할일 삭제 중 오류:', error);
showNotification('서버 연결에 실패했습니다.', 'error');
} finally {
setIsLoading(false);
}
};
// 유틸리티 함수들
const getStatusClass = (status) => {
switch(status) {
case '0': return 'bg-gray-500/20 text-gray-300';
case '1': return 'bg-primary-500/20 text-primary-300';
case '2': return 'bg-danger-500/20 text-danger-300';
case '3': return 'bg-warning-500/20 text-warning-300';
case '5': return 'bg-success-500/20 text-success-300';
default: return 'bg-white/10 text-white/50';
}
};
const getStatusText = (status) => {
switch(status) {
case '0': return '대기';
case '1': return '진행';
case '2': return '취소';
case '3': return '보류';
case '5': return '완료';
default: return '대기';
}
};
const getSeqnoClass = (seqno) => {
switch(seqno) {
case 1: return 'bg-primary-500/20 text-primary-300';
case 2: return 'bg-warning-500/20 text-warning-300';
case 3: return 'bg-danger-500/20 text-danger-300';
default: return 'bg-white/10 text-white/50';
}
};
const getSeqnoText = (seqno) => {
switch(seqno) {
case 1: return '중요';
case 2: return '매우 중요';
case 3: return '긴급';
default: return '보통';
}
};
const formatDate = (dateString) => {
if (!dateString) return '-';
return new Date(dateString).toLocaleDateString('ko-KR');
};
// 알림 표시 함수
const showNotification = (message, type = 'info') => {
const colors = {
info: 'bg-blue-500/90 backdrop-blur-sm',
success: 'bg-green-500/90 backdrop-blur-sm',
warning: 'bg-yellow-500/90 backdrop-blur-sm',
error: 'bg-red-500/90 backdrop-blur-sm'
};
const notification = document.createElement('div');
notification.className = `fixed top-4 right-4 ${colors[type]} text-white px-4 py-3 rounded-lg z-50 transition-all duration-300 transform translate-x-0 opacity-100 shadow-lg border border-white/20`;
notification.innerHTML = `
<div class="flex items-center">
<span class="ml-2">${message}</span>
</div>
`;
notification.style.transform = 'translateX(100%)';
notification.style.opacity = '0';
document.body.appendChild(notification);
setTimeout(() => {
notification.style.transform = 'translateX(0)';
notification.style.opacity = '1';
}, 10);
setTimeout(() => {
notification.style.transform = 'translateX(100%)';
notification.style.opacity = '0';
setTimeout(() => notification.remove(), 300);
}, 3000);
};
// 할일 행 렌더링
const renderTodoRow = (todo, includeOkdate = false) => {
const statusClass = getStatusClass(todo.status);
const statusText = getStatusText(todo.status);
const flagClass = todo.flag ? 'bg-warning-500/20 text-warning-300' : 'bg-white/10 text-white/50';
const flagText = todo.flag ? '고정' : '일반';
const seqnoClass = getSeqnoClass(todo.seqno);
const seqnoText = getSeqnoText(todo.seqno);
const expireText = formatDate(todo.expire);
const isExpired = todo.expire && new Date(todo.expire) < new Date();
const expireClass = isExpired ? 'text-danger-400' : 'text-white/80';
const okdateText = formatDate(todo.okdate);
const okdateClass = todo.okdate ? 'text-success-400' : 'text-white/80';
return (
<tr key={todo.idx} className="hover:bg-white/5 transition-colors cursor-pointer" onClick={() => editTodo(todo.idx)}>
<td className="px-6 py-4 whitespace-nowrap">
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${statusClass}`}>
{statusText}
</span>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${flagClass}`}>
{flagText}
</span>
</td>
<td className="px-6 py-4 text-white">{todo.title || '제목 없음'}</td>
<td className="px-6 py-4 text-white/80 max-w-xs truncate">{todo.remark || ''}</td>
<td className="px-6 py-4 text-white/80">{todo.request || '-'}</td>
<td className="px-6 py-4 whitespace-nowrap">
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${seqnoClass}`}>
{seqnoText}
</span>
</td>
<td className={`px-6 py-4 whitespace-nowrap ${expireClass}`}>{expireText}</td>
{includeOkdate && <td className={`px-6 py-4 whitespace-nowrap ${okdateClass}`}>{okdateText}</td>}
<td className="px-6 py-4 whitespace-nowrap text-sm" onClick={(e) => e.stopPropagation()}>
<button onClick={() => editTodo(todo.idx)} className="text-primary-400 hover:text-primary-300 mr-3 transition-colors">
수정
</button>
<button onClick={() => deleteTodo(todo.idx)} className="text-danger-400 hover:text-danger-300 transition-colors">
삭제
</button>
</td>
</tr>
);
};
return (
<div className="container mx-auto px-4 py-8">
{/* 할일 목록 */}
<div className="glass-effect rounded-2xl overflow-hidden animate-slide-up">
<div className="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 className="text-xl font-semibold text-white flex items-center">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path>
</svg>
할일 목록
</h2>
<button onClick={() => setShowAddModal(true)} className="bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg transition-colors flex items-center text-sm">
<svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
</svg>
할일 추가
</button>
</div>
{/* 탭 메뉴 */}
<div className="px-6 py-2 border-b border-white/10">
<div className="flex space-x-1 bg-white/5 rounded-lg p-1">
<button onClick={() => setCurrentTab('active')} className={`flex-1 px-4 py-2 text-sm font-medium rounded-md transition-all duration-200 ${
currentTab === 'active'
? 'text-white bg-white/20 shadow-sm'
: 'text-white/60 hover:text-white hover:bg-white/10'
}`}>
<div className="flex items-center justify-center space-x-2">
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
</svg>
<span>진행중인 할일</span>
<span className="px-2 py-0.5 text-xs bg-primary-500/30 text-primary-200 rounded-full">{activeTodos.length}</span>
</div>
</button>
<button onClick={() => setCurrentTab('completed')} className={`flex-1 px-4 py-2 text-sm font-medium rounded-md transition-all duration-200 ${
currentTab === 'completed'
? 'text-white bg-white/20 shadow-sm'
: 'text-white/60 hover:text-white hover:bg-white/10'
}`}>
<div className="flex items-center justify-center space-x-2">
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<span>완료된 할일</span>
<span className="px-2 py-0.5 text-xs bg-success-500/30 text-success-200 rounded-full">{completedTodos.length}</span>
</div>
</button>
</div>
</div>
{/* 진행중인 할일 테이블 */}
{currentTab === 'active' && (
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-white/10">
<tr>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">진행상태</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">플래그</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">제목</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">내용</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">요청자</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">중요도</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">만료일</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">작업</th>
</tr>
</thead>
<tbody className="divide-y divide-white/10">
{isLoading ? (
<tr>
<td colSpan="8" className="p-8 text-center">
<div className="inline-flex items-center">
<div className="loading inline-block w-5 h-5 border-3 border-white/30 border-t-white rounded-full animate-spin mr-3"></div>
<span className="text-white/80">데이터를 불러오는 ...</span>
</div>
</td>
</tr>
) : activeTodos.length === 0 ? (
<tr>
<td colSpan="8" className="px-6 py-8 text-center text-white/50">
진행중인 할일이 없습니다
</td>
</tr>
) : (
activeTodos.map(todo => renderTodoRow(todo, false))
)}
</tbody>
</table>
</div>
)}
{/* 완료된 할일 테이블 */}
{currentTab === 'completed' && (
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-white/10">
<tr>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">진행상태</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">플래그</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">제목</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">내용</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">요청자</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">중요도</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">만료일</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">완료일</th>
<th className="px-6 py-4 text-left text-xs font-medium text-white/70 uppercase tracking-wider">작업</th>
</tr>
</thead>
<tbody className="divide-y divide-white/10">
{isLoading ? (
<tr>
<td colSpan="9" className="p-8 text-center">
<div className="inline-flex items-center">
<div className="loading inline-block w-5 h-5 border-3 border-white/30 border-t-white rounded-full animate-spin mr-3"></div>
<span className="text-white/80">데이터를 불러오는 ...</span>
</div>
</td>
</tr>
) : completedTodos.length === 0 ? (
<tr>
<td colSpan="9" className="px-6 py-8 text-center text-white/50">
완료된 할일이 없습니다
</td>
</tr>
) : (
completedTodos.map(todo => renderTodoRow(todo, true))
)}
</tbody>
</table>
</div>
)}
</div>
{/* 로딩 인디케이터 */}
{isLoading && (
<div className="fixed top-4 right-4 bg-white/20 backdrop-blur-sm rounded-full px-4 py-2 text-white text-sm">
<div className="flex items-center">
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white mr-2"></div>
처리 ...
</div>
</div>
)}
{/* 새 할일 추가 모달 */}
{showAddModal && (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50">
<div className="flex items-center justify-center min-h-screen p-4">
<div className="glass-effect rounded-2xl w-full max-w-2xl animate-slide-up">
{/* 모달 헤더 */}
<div className="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 className="text-xl font-semibold text-white flex items-center">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
</svg>
할일 추가
</h2>
<button onClick={() => setShowAddModal(false)} className="text-white/70 hover:text-white transition-colors">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
{/* 모달 내용 */}
<div className="p-6">
<form onSubmit={addTodo} className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-white/70 text-sm font-medium mb-2">제목 (선택사항)</label>
<input
type="text"
value={todoForm.title}
onChange={(e) => setTodoForm({...todoForm, title: e.target.value})}
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="할일 제목을 입력하세요"
/>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">만료일 (선택사항)</label>
<input
type="date"
value={todoForm.expire}
onChange={(e) => setTodoForm({...todoForm, expire: e.target.value})}
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
/>
</div>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">내용 *</label>
<textarea
value={todoForm.remark}
onChange={(e) => setTodoForm({...todoForm, remark: e.target.value})}
rows="3"
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="할일 내용을 입력하세요 (필수)"
required
></textarea>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">요청자</label>
<input
type="text"
value={todoForm.request}
onChange={(e) => setTodoForm({...todoForm, request: e.target.value})}
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="업무 요청자를 입력하세요"
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label className="block text-white/70 text-sm font-medium mb-2">진행상태</label>
<div className="flex flex-wrap gap-2">
{[
{value: '0', label: '대기', class: 'bg-gray-500/20 text-gray-300'},
{value: '1', label: '진행', class: 'bg-primary-500/20 text-primary-300'},
{value: '3', label: '보류', class: 'bg-warning-500/20 text-warning-300'},
{value: '2', label: '취소', class: 'bg-danger-500/20 text-danger-300'},
{value: '5', label: '완료', class: 'bg-success-500/20 text-success-300'}
].map(status => (
<button
key={status.value}
type="button"
onClick={() => setTodoForm({...todoForm, status: status.value})}
className={`px-3 py-1 rounded-lg text-xs font-medium transition-all ${
todoForm.status === status.value
? status.class + ' border-' + status.class.split(' ')[0].replace('bg-', '').replace('/20', '/30')
: 'bg-white/10 text-white/50 border border-white/20 hover:bg-white/20'
}`}
>
{status.label}
</button>
))}
</div>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">중요도</label>
<select
value={todoForm.seqno}
onChange={(e) => setTodoForm({...todoForm, seqno: parseInt(e.target.value)})}
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
>
<option value="0">보통</option>
<option value="1">중요</option>
<option value="2">매우 중요</option>
<option value="3">긴급</option>
</select>
</div>
<div className="flex items-end">
<label className="flex items-center text-white/70 text-sm font-medium">
<input
type="checkbox"
checked={todoForm.flag}
onChange={(e) => setTodoForm({...todoForm, flag: e.target.checked})}
className="mr-2 text-primary-500 focus:ring-primary-400 focus:ring-offset-0 rounded"
/>
플래그 (상단 고정)
</label>
</div>
</div>
</form>
</div>
{/* 모달 푸터 */}
<div className="px-6 py-4 border-t border-white/10 flex justify-end space-x-3">
<button type="button" onClick={() => setShowAddModal(false)} className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors">
취소
</button>
<button type="submit" form="todoForm" onClick={addTodo} className="bg-primary-500 hover:bg-primary-600 text-white px-6 py-2 rounded-lg transition-colors flex items-center">
<svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
</svg>
추가
</button>
</div>
</div>
</div>
</div>
)}
{/* 수정 모달 */}
{showEditModal && (
<div className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50">
<div className="flex items-center justify-center min-h-screen p-4">
<div className="glass-effect rounded-2xl w-full max-w-2xl animate-slide-up">
{/* 모달 헤더 */}
<div className="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<h2 className="text-xl font-semibold text-white flex items-center">
<svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"></path>
</svg>
할일 수정
</h2>
<button onClick={() => {setShowEditModal(false); setCurrentEditId(null);}} className="text-white/70 hover:text-white transition-colors">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>
{/* 모달 내용 */}
<div className="p-6">
<div className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="block text-white/70 text-sm font-medium mb-2">제목 (선택사항)</label>
<input
type="text"
value={editForm.title}
onChange={(e) => setEditForm({...editForm, title: e.target.value})}
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="할일 제목을 입력하세요"
/>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">만료일 (선택사항)</label>
<input
type="date"
value={editForm.expire}
onChange={(e) => setEditForm({...editForm, expire: e.target.value})}
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
/>
</div>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">내용 *</label>
<textarea
value={editForm.remark}
onChange={(e) => setEditForm({...editForm, remark: e.target.value})}
rows="3"
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="할일 내용을 입력하세요 (필수)"
required
></textarea>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">요청자</label>
<input
type="text"
value={editForm.request}
onChange={(e) => setEditForm({...editForm, request: e.target.value})}
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
placeholder="업무 요청자를 입력하세요"
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label className="block text-white/70 text-sm font-medium mb-2">진행상태</label>
<div className="flex flex-wrap gap-2">
{[
{value: '0', label: '대기', class: 'bg-gray-500/20 text-gray-300'},
{value: '1', label: '진행', class: 'bg-primary-500/20 text-primary-300'},
{value: '3', label: '보류', class: 'bg-warning-500/20 text-warning-300'},
{value: '2', label: '취소', class: 'bg-danger-500/20 text-danger-300'},
{value: '5', label: '완료', class: 'bg-success-500/20 text-success-300'}
].map(status => (
<button
key={status.value}
type="button"
onClick={() => updateTodoStatus(status.value)}
className={`px-3 py-1 rounded-lg text-xs font-medium transition-all ${
editForm.status === status.value
? status.class + ' border-' + status.class.split(' ')[0].replace('bg-', '').replace('/20', '/30')
: 'bg-white/10 text-white/50 border border-white/20 hover:bg-white/20'
}`}
>
{status.label}
</button>
))}
</div>
</div>
<div>
<label className="block text-white/70 text-sm font-medium mb-2">중요도</label>
<select
value={editForm.seqno}
onChange={(e) => setEditForm({...editForm, seqno: parseInt(e.target.value)})}
className="w-full bg-white/20 backdrop-blur-sm border border-white/30 rounded-lg px-4 py-2 text-white focus:outline-none focus:ring-2 focus:ring-primary-400 transition-all"
>
<option value="0">보통</option>
<option value="1">중요</option>
<option value="2">매우 중요</option>
<option value="3">긴급</option>
</select>
</div>
<div>
<label className="flex items-center text-white/70 text-sm font-medium mt-6">
<input
type="checkbox"
checked={editForm.flag}
onChange={(e) => setEditForm({...editForm, flag: e.target.checked})}
className="mr-2 text-primary-500 focus:ring-primary-400 focus:ring-offset-0 rounded"
/>
플래그 (상단 고정)
</label>
</div>
</div>
</div>
</div>
{/* 모달 푸터 */}
<div className="px-6 py-4 border-t border-white/10 flex justify-end space-x-3">
<button onClick={() => {setShowEditModal(false); setCurrentEditId(null);}} className="bg-white/20 hover:bg-white/30 text-white px-4 py-2 rounded-lg transition-colors">
취소
</button>
<button onClick={updateTodo} className="bg-primary-500 hover:bg-primary-600 text-white px-6 py-2 rounded-lg transition-colors">
수정
</button>
</div>
</div>
</div>
</div>
)}
</div>
);
}

View File

@@ -1,270 +0,0 @@
<!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>
<!-- Tailwind 설정 -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
100: '#dbeafe',
200: '#bfdbfe',
300: '#93c5fd',
400: '#60a5fa',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
},
success: {
50: '#f0fdf4',
100: '#dcfce7',
200: '#bbf7d0',
300: '#86efac',
400: '#4ade80',
500: '#22c55e',
600: '#16a34a',
700: '#15803d',
800: '#166534',
900: '#14532d',
},
warning: {
50: '#fffbeb',
100: '#fef3c7',
200: '#fde68a',
300: '#fcd34d',
400: '#fbbf24',
500: '#f59e0b',
600: '#d97706',
700: '#b45309',
800: '#92400e',
900: '#78350f',
},
danger: {
50: '#fef2f2',
100: '#fee2e2',
200: '#fecaca',
300: '#fca5a5',
400: '#f87171',
500: '#ef4444',
600: '#dc2626',
700: '#b91c1c',
800: '#991b1b',
900: '#7f1d1d',
}
},
animation: {
'fade-in': 'fadeIn 0.5s ease-in-out',
'slide-up': 'slideUp 0.3s ease-out',
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
slideUp: {
'0%': { transform: 'translateY(10px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
}
}
}
}
}
</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;
}
/* 테이블 셀 텍스트 오버플로우 처리 */
.truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* 값(문자열) 열 최대 너비 제한 */
.svalue-cell {
max-width: 128px; /* w-32 = 128px */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* 개발중 경고 스타일 */
.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-common-app" class="animate-fade-in">
<div class="container mx-auto px-4 py-8">
<div class="flex gap-6 h-[calc(100vh-200px)]">
<!-- 좌측 스켈레톤 -->
<div class="w-80">
<div class="glass-effect rounded-2xl h-full animate-pulse">
<div class="p-4 border-b border-white/10">
<div class="h-6 bg-white/20 rounded w-3/4"></div>
</div>
<div class="p-4 space-y-3">
<div class="h-16 bg-white/10 rounded-lg"></div>
<div class="h-16 bg-white/10 rounded-lg"></div>
<div class="h-16 bg-white/10 rounded-lg"></div>
</div>
</div>
</div>
<!-- 우측 스켈레톤 -->
<div class="flex-1">
<div class="glass-effect rounded-2xl h-full animate-pulse">
<div class="p-4 border-b border-white/10 flex justify-between items-center">
<div class="h-6 bg-white/20 rounded w-1/3"></div>
<div class="h-8 bg-white/20 rounded w-20"></div>
</div>
<div class="p-4">
<div class="space-y-3">
<div class="h-10 bg-white/10 rounded"></div>
<div class="h-10 bg-white/10 rounded"></div>
<div class="h-10 bg-white/10 rounded"></div>
<div class="h-10 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>
<!-- App 컴포넌트 -->
<script type="text/babel">
const { useState, useEffect } = React;
function App() {
return (
<div>
<CommonNavigation currentPage="common" />
<CommonCode />
</div>
);
}
</script>
<!-- 공용코드 컴포넌트 로드 -->
<script type="text/babel" src="/react/component/CommonCode"></script>
<!-- 앱 초기화 -->
<script type="text/babel">
const root = ReactDOM.createRoot(document.getElementById('react-common-app'));
root.render(<App />);
</script>
</body>
</html>

View File

@@ -1,297 +0,0 @@
<!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">
<meta name="version" content="v2.0-20250905-react">
<title>근태현황 대시보드 (React)</title>
<link rel="stylesheet" href="/lib/css/tailwind.min.css">
<script src="/lib/js/tailwind-config.js"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
100: '#dbeafe',
200: '#bfdbfe',
300: '#93c5fd',
400: '#60a5fa',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
},
success: {
50: '#f0fdf4',
100: '#dcfce7',
200: '#bbf7d0',
300: '#86efac',
400: '#4ade80',
500: '#22c55e',
600: '#16a34a',
700: '#15803d',
800: '#166534',
900: '#14532d',
},
warning: {
50: '#fffbeb',
100: '#fef3c7',
200: '#fde68a',
300: '#fcd34d',
400: '#fbbf24',
500: '#f59e0b',
600: '#d97706',
700: '#b45309',
800: '#92400e',
900: '#78350f',
},
danger: {
50: '#fef2f2',
100: '#fee2e2',
200: '#fecaca',
300: '#fca5a5',
400: '#f87171',
500: '#ef4444',
600: '#dc2626',
700: '#b91c1c',
800: '#991b1b',
900: '#7f1d1d',
}
},
animation: {
'fade-in': 'fadeIn 0.5s ease-in-out',
'slide-up': 'slideUp 0.3s ease-out',
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
slideUp: {
'0%': { transform: 'translateY(10px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
}
}
}
}
}
</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);
}
/* React 컴포넌트 로딩 스타일 */
.react-dashboard-container {
min-height: 100vh;
}
.loading-skeleton {
background: linear-gradient(90deg, rgba(255,255,255,0.1) 25%, rgba(255,255,255,0.2) 50%, rgba(255,255,255,0.1) 75%);
background-size: 200% 100%;
animation: loading 1.5s infinite;
}
@keyframes loading {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
</style>
</head>
<body>
<div id="react-dashboard-app" class="react-dashboard-container">
<!-- 로딩 화면 -->
<div class="bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 min-h-screen text-white">
<div class="container mx-auto px-4 py-8">
<!-- 로딩 헤더 -->
<div class="text-center mb-8">
<div class="loading-skeleton h-10 w-80 mx-auto rounded-lg mb-4"></div>
<div class="loading-skeleton h-6 w-60 mx-auto rounded-lg mb-2"></div>
<div class="loading-skeleton h-4 w-40 mx-auto rounded-lg"></div>
</div>
<!-- 로딩 통계 카드들 -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-6 mb-8">
<div class="glass-effect rounded-2xl p-6">
<div class="flex items-center justify-between">
<div>
<div class="loading-skeleton h-4 w-16 rounded mb-2"></div>
<div class="loading-skeleton h-8 w-12 rounded"></div>
</div>
<div class="w-12 h-12 bg-success-500/20 rounded-full flex items-center justify-center">
<div class="loading-skeleton w-6 h-6 rounded"></div>
</div>
</div>
</div>
<div class="glass-effect rounded-2xl p-6">
<div class="flex items-center justify-between">
<div>
<div class="loading-skeleton h-4 w-16 rounded mb-2"></div>
<div class="loading-skeleton h-8 w-12 rounded"></div>
</div>
<div class="w-12 h-12 bg-warning-500/20 rounded-full flex items-center justify-center">
<div class="loading-skeleton w-6 h-6 rounded"></div>
</div>
</div>
</div>
<div class="glass-effect rounded-2xl p-6">
<div class="flex items-center justify-between">
<div>
<div class="loading-skeleton h-4 w-16 rounded mb-2"></div>
<div class="loading-skeleton h-8 w-12 rounded"></div>
</div>
<div class="w-12 h-12 bg-primary-500/20 rounded-full flex items-center justify-center">
<div class="loading-skeleton w-6 h-6 rounded"></div>
</div>
</div>
</div>
<div class="glass-effect rounded-2xl p-6">
<div class="flex items-center justify-between">
<div>
<div class="loading-skeleton h-4 w-20 rounded mb-2"></div>
<div class="loading-skeleton h-8 w-12 rounded"></div>
</div>
<div class="w-12 h-12 bg-danger-500/20 rounded-full flex items-center justify-center">
<div class="loading-skeleton w-6 h-6 rounded"></div>
</div>
</div>
</div>
<div class="glass-effect rounded-2xl p-6">
<div class="flex items-center justify-between">
<div>
<div class="loading-skeleton h-4 w-20 rounded mb-2"></div>
<div class="loading-skeleton h-8 w-12 rounded"></div>
</div>
<div class="w-12 h-12 bg-purple-500/20 rounded-full flex items-center justify-center">
<div class="loading-skeleton w-6 h-6 rounded"></div>
</div>
</div>
</div>
</div>
<!-- 로딩 추가 정보 -->
<div class="glass-effect rounded-2xl p-6">
<div class="loading-skeleton h-8 w-32 rounded mb-4"></div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="text-center">
<div class="w-16 h-16 bg-success-500/20 rounded-full mx-auto mb-2">
<div class="loading-skeleton w-full h-full rounded-full"></div>
</div>
<div class="loading-skeleton h-4 w-16 rounded mx-auto mb-1"></div>
<div class="loading-skeleton h-3 w-24 rounded mx-auto"></div>
</div>
<div class="text-center">
<div class="w-16 h-16 bg-warning-500/20 rounded-full mx-auto mb-2">
<div class="loading-skeleton w-full h-full rounded-full"></div>
</div>
<div class="loading-skeleton h-4 w-16 rounded mx-auto mb-1"></div>
<div class="loading-skeleton h-3 w-24 rounded mx-auto"></div>
</div>
<div class="text-center">
<div class="w-16 h-16 bg-primary-500/20 rounded-full mx-auto mb-2">
<div class="loading-skeleton w-full h-full rounded-full"></div>
</div>
<div class="loading-skeleton h-4 w-16 rounded mx-auto mb-1"></div>
<div class="loading-skeleton h-3 w-24 rounded mx-auto"></div>
</div>
</div>
</div>
<!-- 로딩 텍스트 -->
<div class="text-center mt-8">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-white mx-auto mb-4"></div>
<p class="text-white/70">React Dashboard 컴포넌트를 로딩 중입니다...</p>
</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>
<!-- Dashboard 컴포넌트 -->
<script type="text/babel" src="/react/component/DashboardApp"></script>
<!-- 앱 초기화 -->
<script type="text/babel">
const { useState, useEffect } = React;
function App() {
console.log('✅ App 컴포넌트 렌더링 시작');
console.log('📊 CommonNavigation 사용 가능:', typeof CommonNavigation);
console.log('📊 DashboardApp 사용 가능:', typeof DashboardApp);
console.log('📊 DevWarning 사용 가능:', typeof DevWarning);
return (
<div>
<CommonNavigation currentPage="dashboard" />
<DashboardApp />
<DevWarning show={false} />
</div>
);
}
// 루트 렌더링
const root = ReactDOM.createRoot(document.getElementById('react-dashboard-app'));
root.render(<App />);
console.log('✅ React Dashboard 앱이 마운트되었습니다.');
</script>
</body>
</html>

View File

@@ -1,261 +0,0 @@
<!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>

View File

@@ -1,120 +0,0 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React JSX Test - GroupWare</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
margin: 0;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
.container {
max-width: 900px;
margin: 0 auto;
background-color: white;
padding: 30px;
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}
.header {
text-align: center;
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 2px solid #f0f0f0;
}
.header h1 {
color: #333;
margin: 0;
font-size: 2.5em;
}
.header p {
color: #666;
font-size: 1.2em;
margin: 10px 0;
}
.status {
padding: 20px;
margin: 20px 0;
border-radius: 8px;
}
.success {
background-color: #d4edda;
border: 1px solid #c3e6cb;
color: #155724;
}
.loading {
background-color: #fff3cd;
border: 1px solid #ffeaa7;
color: #856404;
}
.error {
background-color: #f8d7da;
border: 1px solid #f5c6cb;
color: #721c24;
}
.tech-info {
background-color: #e3f2fd;
border: 1px solid #90caf9;
color: #0d47a1;
margin: 20px 0;
padding: 15px;
border-radius: 8px;
}
.version-info {
font-size: 0.9em;
color: #666;
text-align: center;
margin-top: 30px;
padding: 15px;
background-color: #f8f9fa;
border-radius: 8px;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🚀 React JSX Integration</h1>
<p>GroupWare + OWIN + React + JSX 모듈화 테스트</p>
<div class="tech-info">
<strong>기술 스택:</strong> C# WinForms + OWIN + React 18 + Babel JSX + 모듈화된 컴포넌트
</div>
</div>
<div id="react-app">
<div class="status loading">
React JSX 컴포넌트를 로딩 중입니다...
</div>
</div>
<div class="version-info">
<p><strong>환경:</strong> .NET Framework 4.6 + OWIN + React 18.2.0</p>
<p><strong>포트:</strong> 7979 | <strong>파일 위치:</strong> /react-jsx-test.html</p>
</div>
</div>
<!-- React & ReactDOM CDN -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!-- Babel standalone for JSX -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- JSX Component Import -->
<script type="text/babel" src="/react/component/TestApp"></script>
<!-- App Initialization -->
<script type="text/babel">
// JSX 컴포넌트를 DOM에 렌더링
const root = ReactDOM.createRoot(document.getElementById('react-app'));
root.render(<TestApp />);
console.log('✅ React JSX 컴포넌트가 성공적으로 마운트되었습니다.');
console.log('📁 컴포넌트 파일: /react/TestApp.jsx');
console.log('🌐 테스트 페이지: /react-jsx-test.html');
</script>
</body>
</html>

View File

@@ -1,241 +0,0 @@
<!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>
<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);
}
.loading {
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid rgba(255, 255, 255, 0.3);
border-top: 3px solid #ffffff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.table-container {
max-height: 600px;
overflow-y: auto;
}
/* 스크롤바 스타일링 */
.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;
}
/* 개발중 경고 스타일 */
.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-kuntae-app" class="animate-fade-in">
<div class="container mx-auto px-4 py-8">
<div class="space-y-6">
{/* 경고 메시지 스켈레톤 */}
<div class="bg-white/10 rounded-lg p-4 animate-pulse">
<div class="h-6 bg-white/20 rounded w-3/4"></div>
</div>
{/* 필터 스켈레톤 */}
<div class="glass-effect rounded-lg p-6 animate-pulse">
<div class="grid grid-cols-3 gap-4">
<div class="h-16 bg-white/10 rounded"></div>
<div class="h-16 bg-white/10 rounded"></div>
<div class="h-16 bg-white/10 rounded"></div>
</div>
</div>
{/* 통계 카드 스켈레톤 */}
<div class="grid grid-cols-1 md:grid-cols-4 gap-6">
<div class="glass-effect rounded-lg p-6 animate-pulse">
<div class="flex items-center">
<div class="w-12 h-12 bg-white/20 rounded-lg mr-4"></div>
<div>
<div class="h-4 bg-white/20 rounded w-20 mb-2"></div>
<div class="h-6 bg-white/20 rounded w-12"></div>
</div>
</div>
</div>
<div class="glass-effect rounded-lg p-6 animate-pulse">
<div class="flex items-center">
<div class="w-12 h-12 bg-white/20 rounded-lg mr-4"></div>
<div>
<div class="h-4 bg-white/20 rounded w-16 mb-2"></div>
<div class="h-6 bg-white/20 rounded w-8"></div>
</div>
</div>
</div>
<div class="glass-effect rounded-lg p-6 animate-pulse">
<div class="flex items-center">
<div class="w-12 h-12 bg-white/20 rounded-lg mr-4"></div>
<div>
<div class="h-4 bg-white/20 rounded w-16 mb-2"></div>
<div class="h-6 bg-white/20 rounded w-8"></div>
</div>
</div>
</div>
<div class="glass-effect rounded-lg p-6 animate-pulse">
<div class="flex items-center">
<div class="w-12 h-12 bg-white/20 rounded-lg mr-4"></div>
<div>
<div class="h-4 bg-white/20 rounded w-16 mb-2"></div>
<div class="h-6 bg-white/20 rounded w-8"></div>
</div>
</div>
</div>
</div>
{/* 테이블 스켈레톤 */}
<div class="glass-effect rounded-lg p-4 animate-pulse">
<div class="space-y-3">
<div class="grid grid-cols-7 gap-4">
<div class="h-6 bg-white/20 rounded"></div>
<div class="h-6 bg-white/20 rounded"></div>
<div class="h-6 bg-white/20 rounded"></div>
<div class="h-6 bg-white/20 rounded"></div>
<div class="h-6 bg-white/20 rounded"></div>
<div class="h-6 bg-white/20 rounded"></div>
<div class="h-6 bg-white/20 rounded"></div>
</div>
<div class="space-y-2">
<div class="grid grid-cols-7 gap-4">
<div class="h-4 bg-white/10 rounded"></div>
<div class="h-4 bg-white/10 rounded"></div>
<div class="h-4 bg-white/10 rounded"></div>
<div class="h-4 bg-white/10 rounded"></div>
<div class="h-4 bg-white/10 rounded"></div>
<div class="h-4 bg-white/10 rounded"></div>
<div class="h-4 bg-white/10 rounded"></div>
</div>
<div class="grid grid-cols-7 gap-4">
<div class="h-4 bg-white/10 rounded"></div>
<div class="h-4 bg-white/10 rounded"></div>
<div class="h-4 bg-white/10 rounded"></div>
<div class="h-4 bg-white/10 rounded"></div>
<div class="h-4 bg-white/10 rounded"></div>
<div class="h-4 bg-white/10 rounded"></div>
<div class="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" src="/react/component/Kuntae"></script>
<!-- 앱 컴포넌트 -->
<script type="text/babel">
const { useState, useEffect } = React;
function App() {
return (
<div>
<CommonNavigation currentPage="kuntae" />
<Kuntae />
<DevWarning />
</div>
);
}
// 루트 렌더링
const root = ReactDOM.createRoot(document.getElementById('react-kuntae-app'));
root.render(<App />);
</script>
</body>
</html>

View File

@@ -1,177 +0,0 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>로그인 - GroupWare (React)</title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
100: '#dbeafe',
200: '#bfdbfe',
300: '#93c5fd',
400: '#60a5fa',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
},
success: {
50: '#f0fdf4',
100: '#dcfce7',
200: '#bbf7d0',
300: '#86efac',
400: '#4ade80',
500: '#22c55e',
600: '#16a34a',
700: '#15803d',
800: '#166534',
900: '#14532d',
},
warning: {
50: '#fffbeb',
100: '#fef3c7',
200: '#fde68a',
300: '#fcd34d',
400: '#fbbf24',
500: '#f59e0b',
600: '#d97706',
700: '#b45309',
800: '#92400e',
900: '#78350f',
},
danger: {
50: '#fef2f2',
100: '#fee2e2',
200: '#fecaca',
300: '#fca5a5',
400: '#f87171',
500: '#ef4444',
600: '#dc2626',
700: '#b91c1c',
800: '#991b1b',
900: '#7f1d1d',
}
},
animation: {
'fade-in': 'fadeIn 0.6s ease-in-out',
'slide-up': 'slideUp 0.4s ease-out',
'bounce-in': 'bounceIn 0.6s ease-out',
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
slideUp: {
'0%': { transform: 'translateY(20px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
},
bounceIn: {
'0%': { transform: 'scale(0.3)', opacity: '0' },
'50%': { transform: 'scale(1.05)' },
'70%': { transform: 'scale(0.9)' },
'100%': { transform: 'scale(1)', opacity: '1' },
}
}
}
}
}
</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(-2px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.input-focus {
transition: all 0.3s ease;
}
.input-focus:focus {
transform: scale(1.02);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.floating-label {
transition: all 0.3s ease;
}
.input-field:focus + .floating-label,
.input-field:not(:placeholder-shown) + .floating-label {
transform: translateY(-1.5rem) scale(0.85);
color: #3b82f6;
}
/* 드롭다운 스타일 */
select.input-field option {
background-color: #1f2937;
color: white;
}
select.input-field:focus option:checked {
background-color: #3b82f6;
}
select.input-field option:hover {
background-color: #374151;
}
/* React 컴포넌트 전용 스타일 */
.react-login-container {
min-height: 100vh;
}
</style>
</head>
<body>
<div id="react-login-app" class="react-login-container">
<div class="gradient-bg min-h-screen flex items-center justify-center p-4">
<div class="w-full max-w-md">
<div class="glass-effect rounded-3xl p-8 card-hover">
<div class="text-center">
<div class="w-16 h-16 bg-white/20 rounded-full flex items-center justify-center mx-auto mb-4">
<svg class="w-8 h-8 text-white animate-pulse" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"></path>
</svg>
</div>
<h1 class="text-2xl font-bold text-white mb-2">GroupWare</h1>
<p class="text-white/70 text-sm">React 로그인 컴포넌트를 로딩 중입니다...</p>
<div class="mt-6">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-white mx-auto"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- React & ReactDOM CDN -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!-- Babel standalone for JSX -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- React Login Component -->
<script type="text/babel" src="/react/component/LoginApp"></script>
<!-- App Initialization -->
<script type="text/babel">
const root = ReactDOM.createRoot(document.getElementById('react-login-app'));
root.render(<LoginApp />);
console.log('✅ React 로그인 페이지가 성공적으로 마운트되었습니다.');
console.log('📁 컴포넌트 파일: /react/LoginApp.jsx');
console.log('🌐 페이지 URL: /react/login');
</script>
</body>
</html>

View File

@@ -1,191 +0,0 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>프로젝트 관리 - GroupWare (React)</title>
<link rel="stylesheet" href="/lib/css/tailwind.min.css">
<script src="/lib/js/tailwind-config.js"></script>
<style>
.glass-effect {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.animate-slide-up {
animation: slideUp 0.5s ease-out;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.custom-scrollbar::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.3);
border-radius: 3px;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.5);
}
.bg-primary-500 {
background-color: #3b82f6;
}
.bg-primary-600 {
background-color: #2563eb;
}
.hover\:bg-primary-600:hover {
background-color: #2563eb;
}
.bg-green-500 {
background-color: #10b981;
}
.bg-green-600 {
background-color: #059669;
}
.hover\:bg-green-600:hover {
background-color: #059669;
}
.bg-red-500 {
background-color: #ef4444;
}
.bg-red-600 {
background-color: #dc2626;
}
.hover\:bg-red-600:hover {
background-color: #dc2626;
}
select option {
background-color: #1f2937;
color: white;
padding: 8px;
}
select option:hover {
background-color: #374151;
}
select option:checked {
background-color: #3b82f6;
}
select option:focus {
background-color: #374151;
}
.loading {
border: 3px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top: 3px solid #fff;
width: 20px;
height: 20px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body class="bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 min-h-screen text-white">
<div id="react-project">
<!-- 스켈레톤 로딩 UI -->
<div class="container mx-auto px-4 py-8">
<div class="glass-effect rounded-lg overflow-hidden animate-pulse">
<div class="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<div class="h-6 bg-white/20 rounded w-40"></div>
<div class="flex space-x-3">
<div class="h-10 bg-white/20 rounded w-32"></div>
<div class="h-10 bg-white/20 rounded w-24"></div>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 p-4">
<div class="bg-white/10 rounded-lg p-4">
<div class="h-8 bg-white/20 rounded mb-2"></div>
<div class="h-4 bg-white/20 rounded w-16"></div>
</div>
<div class="bg-white/10 rounded-lg p-4">
<div class="h-8 bg-white/20 rounded mb-2"></div>
<div class="h-4 bg-white/20 rounded w-16"></div>
</div>
<div class="bg-white/10 rounded-lg p-4">
<div class="h-8 bg-white/20 rounded mb-2"></div>
<div class="h-4 bg-white/20 rounded w-16"></div>
</div>
<div class="bg-white/10 rounded-lg p-4">
<div class="h-8 bg-white/20 rounded mb-2"></div>
<div class="h-4 bg-white/20 rounded w-16"></div>
</div>
</div>
<div class="p-6">
<div class="space-y-4">
<div class="h-4 bg-white/20 rounded w-full"></div>
<div class="h-4 bg-white/20 rounded w-3/4"></div>
<div class="h-4 bg-white/20 rounded w-1/2"></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>
<!-- Project 컴포넌트 -->
<script type="text/babel" src="/react/component/Project"></script>
<!-- 앱 초기화 -->
<script type="text/babel">
const { useState, useEffect } = React;
function App() {
return (
<div>
<CommonNavigation currentPage="project" />
<Project />
<DevWarning />
</div>
);
}
// 루트 렌더링
const root = ReactDOM.createRoot(document.getElementById('react-project'));
root.render(<App />);
</script>
</body>
</html>

View File

@@ -1,197 +0,0 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React Test Page - GroupWare</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.header {
text-align: center;
margin-bottom: 30px;
}
.status {
padding: 20px;
margin: 20px 0;
border-radius: 5px;
}
.success {
background-color: #d4edda;
border: 1px solid #c3e6cb;
color: #155724;
}
.loading {
background-color: #fff3cd;
border: 1px solid #ffeaa7;
color: #856404;
}
.error {
background-color: #f8d7da;
border: 1px solid #f5c6cb;
color: #721c24;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🚀 React Integration Test</h1>
<p>GroupWare + OWIN + React 통합 테스트</p>
</div>
<div id="react-app">
<div class="status loading">
React 컴포넌트를 로딩 중입니다...
</div>
</div>
</div>
<!-- React & ReactDOM CDN -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!-- Babel standalone for JSX -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<!-- React Component -->
<script type="text/babel">
const { useState, useEffect } = React;
// 메인 React 컴포넌트
function ReactTestApp() {
const [status, setStatus] = useState('loading');
const [counter, setCounter] = useState(0);
const [serverTime, setServerTime] = useState('');
const [apiTest, setApiTest] = useState({ status: 'pending', message: '' });
// 컴포넌트가 마운트될 때 실행
useEffect(() => {
// React가 정상적으로 로드되었음을 표시
setTimeout(() => {
setStatus('success');
setServerTime(new Date().toLocaleString('ko-KR'));
}, 1000);
// API 테스트 (GroupWare의 기존 컨트롤러 테스트)
testAPI();
}, []);
// GroupWare API 테스트 함수
const testAPI = async () => {
try {
// Home 컨트롤러 테스트 (기존에 있을 것으로 예상)
const response = await fetch('/Home');
if (response.ok) {
setApiTest({ status: 'success', message: 'API 연결 성공' });
} else {
setApiTest({ status: 'warning', message: `API 응답: ${response.status}` });
}
} catch (error) {
setApiTest({ status: 'error', message: `API 오류: ${error.message}` });
}
};
return (
<div>
<div className={`status ${status === 'success' ? 'success' : 'loading'}`}>
{status === 'success' ? (
<div>
<h3> React 컴포넌트가 성공적으로 로드되었습니다!</h3>
<p><strong>현재 시간:</strong> {serverTime}</p>
</div>
) : (
<h3>React 컴포넌트를 로딩 중입니다...</h3>
)}
</div>
{status === 'success' && (
<div>
<div className="status">
<h3>📊 상태 관리 테스트</h3>
<p><strong>카운터:</strong> {counter}</p>
<button
onClick={() => setCounter(counter + 1)}
style={{
padding: '10px 20px',
marginRight: '10px',
backgroundColor: '#007bff',
color: 'white',
border: 'none',
borderRadius: '5px',
cursor: 'pointer'
}}
>
증가 (+1)
</button>
<button
onClick={() => setCounter(0)}
style={{
padding: '10px 20px',
backgroundColor: '#6c757d',
color: 'white',
border: 'none',
borderRadius: '5px',
cursor: 'pointer'
}}
>
리셋
</button>
</div>
<div className={`status ${
apiTest.status === 'success' ? 'success' :
apiTest.status === 'error' ? 'error' : 'loading'
}`}>
<h3>🌐 API 연결 테스트</h3>
<p><strong>상태:</strong> {apiTest.message}</p>
<button
onClick={testAPI}
style={{
padding: '10px 20px',
backgroundColor: '#28a745',
color: 'white',
border: 'none',
borderRadius: '5px',
cursor: 'pointer'
}}
>
API 다시 테스트
</button>
</div>
<div className="status">
<h3>📋 통합 테스트 체크리스트</h3>
<ul style={{ textAlign: 'left' }}>
<li> OWIN 정적 파일 서빙</li>
<li> React 라이브러리 로딩 (CDN)</li>
<li> JSX 컴파일 (Babel)</li>
<li> React Hooks (useState, useEffect)</li>
<li> 이벤트 핸들링</li>
<li> API 호출 (fetch)</li>
<li> 반응형 UI 업데이트</li>
</ul>
</div>
</div>
)}
</div>
);
}
// React 컴포넌트를 DOM에 렌더링
const root = ReactDOM.createRoot(document.getElementById('react-app'));
root.render(<ReactTestApp />);
</script>
</body>
</html>

View File

@@ -1,115 +0,0 @@
<!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">
<meta name="version" content="v1.0-20250127">
<title>할일 관리 - GroupWare (React)</title>
<link rel="stylesheet" href="/lib/css/tailwind.min.css">
<script src="/lib/js/tailwind-config.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: 8px;
}
.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);
}
.loading {
border: 3px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top: 3px solid #fff;
width: 20px;
height: 20px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body class="bg-gradient-to-br from-blue-900 via-purple-900 to-indigo-900 min-h-screen text-white">
<div id="react-todo">
<!-- 스켈레톤 로딩 UI -->
<div class="container mx-auto px-4 py-8">
<div class="glass-effect rounded-2xl overflow-hidden animate-pulse">
<div class="px-6 py-4 border-b border-white/10 flex items-center justify-between">
<div class="h-6 bg-white/20 rounded w-40"></div>
<div class="h-10 bg-white/20 rounded w-32"></div>
</div>
<div class="p-6">
<div class="space-y-4">
<div class="h-4 bg-white/20 rounded w-full"></div>
<div class="h-4 bg-white/20 rounded w-3/4"></div>
<div class="h-4 bg-white/20 rounded w-1/2"></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>
<!-- Todo 컴포넌트 -->
<script type="text/babel" src="/react/component/Todo"></script>
<!-- 앱 초기화 -->
<script type="text/babel">
const { useState, useEffect } = React;
function App() {
return (
<div>
<CommonNavigation currentPage="todo" />
<Todo />
<DevWarning />
</div>
);
}
// 루트 렌더링
const root = ReactDOM.createRoot(document.getElementById('react-todo'));
root.render(<App />);
</script>
</body>
</html>

View File

@@ -1092,6 +1092,12 @@ namespace Project
private void ToolStripMenuItem_Click(object sender, EventArgs e) private void ToolStripMenuItem_Click(object sender, EventArgs e)
{ {
int curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.otconfirm));
//if(curLevel < 5)
//{
// Util.MsgE("이 기능을 사용할 권한이 없습니다");
// return;
//}
var f = new FPJ0000.JobReport_.rJobReportOT(); var f = new FPJ0000.JobReport_.rJobReportOT();
f.Show(); f.Show();
} }

Submodule Sub/tcpservice updated: 1680e266da...d7fe2baa0e

View File

@@ -27,7 +27,7 @@ namespace FBS0000
tbGrp.Text = string.Empty; tbGrp.Text = string.Empty;
//this.dv1.CellFormatting += dv1_CellFormatting; //this.dv1.CellFormatting += dv1_CellFormatting;
} }
private void __Load(object sender, EventArgs e) private void __Load(object sender, EventArgs e)
{ {
@@ -95,7 +95,7 @@ namespace FBS0000
//var dtUser = JobReport.OrderBy(t => t.userProcess + t.name).GroupBy(t => t.id);// taUser.GetData(FCOMMON.info.Login.gcode, tbGrp.Text); //var dtUser = JobReport.OrderBy(t => t.userProcess + t.name).GroupBy(t => t.id);// taUser.GetData(FCOMMON.info.Login.gcode, tbGrp.Text);
var dtUser = FCOMMON.DBM.getActiveUserTable(); //업무일지 미사용자로인해서 사용자 목록은 이것을 사용한다 220215 var dtUser = FCOMMON.DBM.getActiveUserTable(); //업무일지 미사용자로인해서 사용자 목록은 이것을 사용한다 220215
int curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
var users = new List<userinfo>(); var users = new List<userinfo>();
var seq = 0; var seq = 0;
foreach (System.Data.DataRow dr in dtUser.Rows) foreach (System.Data.DataRow dr in dtUser.Rows)
@@ -126,9 +126,14 @@ namespace FBS0000
if (dr["outdate"] == null) newuser.outdate = string.Empty; if (dr["outdate"] == null) newuser.outdate = string.Empty;
newuser.outdate = dr["outdate"].ToString(); newuser.outdate = dr["outdate"].ToString();
if (curLevel >= 5 || newuser.empno == FCOMMON.info.Login.no)
{
users.Add(newuser);
seq += 1;
}
users.Add(newuser);
seq += 1;
} }
//휴가테이블에서 데이터를 가져온다 //휴가테이블에서 데이터를 가져온다
@@ -154,8 +159,8 @@ namespace FBS0000
} }
//이월잔액 //이월잔액
var jand = qta.WorkUserJan_Yesterday_Day(FCOMMON.info.Login.gcode, item.empno, sd.ToString("yyyy-01-01"), sd.AddDays(-1).ToShortDateString(), "999999","%"); var jand = qta.WorkUserJan_Yesterday_Day(FCOMMON.info.Login.gcode, item.empno, sd.ToString("yyyy-01-01"), sd.AddDays(-1).ToShortDateString(), "999999", "%");
var jan = qta.WorkUserJan_Yesterday_Day(FCOMMON.info.Login.gcode, item.empno, sd.ToString("yyyy-01-01"), ed.ToShortDateString(), "999999","%"); var jan = qta.WorkUserJan_Yesterday_Day(FCOMMON.info.Login.gcode, item.empno, sd.ToString("yyyy-01-01"), ed.ToShortDateString(), "999999", "%");
var used = 0.0; var used = 0.0;
fpSpread1_Sheet1.Rows[rowindex].ResetBorder(); fpSpread1_Sheet1.Rows[rowindex].ResetBorder();
@@ -212,7 +217,7 @@ namespace FBS0000
//현재인원값 //현재인원값
var bIndate = DateTime.TryParse(item.indate, out DateTime dtIn); var bIndate = DateTime.TryParse(item.indate, out DateTime dtIn);
var bOutdate = DateTime.TryParse(item.outdate, out DateTime dtOut); var bOutdate = DateTime.TryParse(item.outdate, out DateTime dtOut);
// Boolean usePerson = true; // Boolean usePerson = true;
// //
//if (bIndate == true && curDate.ToShortDateString().CompareTo(dtIn.ToShortDateString()) < 0) //if (bIndate == true && curDate.ToShortDateString().CompareTo(dtIn.ToShortDateString()) < 0)
@@ -258,7 +263,7 @@ namespace FBS0000
} }
//근태 시작일자가 조회시작일보다 적다면, 데이터가 걸쳐진 것이므로 회색으로 처리하자 2308320 //근태 시작일자가 조회시작일보다 적다면, 데이터가 걸쳐진 것이므로 회색으로 처리하자 2308320
if(dr.sdate.ToShortDateString().CompareTo(sd.ToShortDateString()) < 0) if (dr.sdate.ToShortDateString().CompareTo(sd.ToShortDateString()) < 0)
{ {
fpSpread1_Sheet1.Cells[rowindex, c].BackColor = Color.DimGray; fpSpread1_Sheet1.Cells[rowindex, c].BackColor = Color.DimGray;
fpSpread1_Sheet1.Cells[rowindex, c].ForeColor = Color.White; fpSpread1_Sheet1.Cells[rowindex, c].ForeColor = Color.White;
@@ -352,7 +357,7 @@ namespace FBS0000
fpSpread1_Sheet1.Columns[c].Tag = ps; fpSpread1_Sheet1.Columns[c].Tag = ps;
} }
used = (float)jand-(float)jan ; used = (float)jand - (float)jan;
//var jan = jand - used; //var jan = jand - used;
fpSpread1_Sheet1.Cells[rowindex, c++].Value = jand != 0 ? jand.ToString() : string.Empty; fpSpread1_Sheet1.Cells[rowindex, c++].Value = jand != 0 ? jand.ToString() : string.Empty;
fpSpread1_Sheet1.Cells[rowindex, c++].Value = used != 0 ? used.ToString() : string.Empty; fpSpread1_Sheet1.Cells[rowindex, c++].Value = used != 0 ? used.ToString() : string.Empty;

View File

@@ -33,7 +33,8 @@ namespace FBS0000
this.tbMon.Text = DateTime.Now.ToShortDateString(); this.tbMon.Text = DateTime.Now.ToShortDateString();
cmbType.SelectedIndex = 0; //일기준으로한다 cmbType.SelectedIndex = 0; //일기준으로한다
int curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.holyday));
if (curLevel < 5) cmbUser.Enabled = false;
} }
private void rJobReport_Load(object sender, EventArgs e) private void rJobReport_Load(object sender, EventArgs e)

View File

@@ -78,8 +78,8 @@ namespace FBS0000
var ed = DateTime.Parse(this.tbMon.Text); var ed = DateTime.Parse(this.tbMon.Text);
var sd = DateTime.Parse(ed.ToString("yyyy") + "-01-01"); var sd = DateTime.Parse(ed.ToString("yyyy") + "-01-01");
//this.reportViewer1.LocalReport.DataSources.Clear(); int curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.holyday));
var uid = "%";// GetUIDValue(); var uid = curLevel > 5 ? "%" : FCOMMON.info.Login.no; // GetUIDValue();
if (cmbType.SelectedIndex == 0) if (cmbType.SelectedIndex == 0)
{ {
taDay.Fill(this.dsReport.Holydata_Day, FCOMMON.info.Login.gcode, uid, sd.ToShortDateString(), ed.ToShortDateString()); taDay.Fill(this.dsReport.Holydata_Day, FCOMMON.info.Login.gcode, uid, sd.ToShortDateString(), ed.ToShortDateString());

View File

@@ -79,14 +79,19 @@ namespace FBS0000
ToolStripMenuItem.Enabled = true; ToolStripMenuItem.Enabled = true;
toolStripButton2.Enabled = true; toolStripButton2.Enabled = true;
toolStripButton3.Enabled = true; toolStripButton3.Enabled = true;
} cmbUser.Enabled = true;
}
else else
{ {
toolStripButton3.Enabled = false; cmbUser.Enabled = false;
toolStripButton3.Enabled = false;
toolStripButton2.Enabled = false; toolStripButton2.Enabled = false;
btSave.Enabled = false; btSave.Enabled = false;
btDel.Enabled = false; btDel.Enabled = false;
btAdd.Enabled = false; btAdd.Enabled = false;
toolStripLabel3.Enabled = false;
RefreshData(); RefreshData();
//this.cmbUser.Enabled = false; //사용자를 고칠수 없게 한다. //this.cmbUser.Enabled = false; //사용자를 고칠수 없게 한다.
@@ -414,9 +419,13 @@ namespace FBS0000
private void toolStripButton5_Click(object sender, EventArgs e) private void toolStripButton5_Click(object sender, EventArgs e)
{ {
//var sd = DateTime.Now.ToString("yyyy-MM-01"); int curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.holyday));
//var ed = DateTime.Parse(DateTime.Now.AddMonths(1).ToString("yyyy-MM-01")).AddDays(-1).ToShortDateString(); if(curLevel < 5)
var f = new WorkTable(); {
AR.UTIL.MsgE("사용 권한이 없습니다");
return;
}
var f = new WorkTable();
f.Show(); f.Show();
} }

View File

@@ -82,6 +82,8 @@ namespace FBS0000
} }
else else
{ {
cmbUser.Enabled = false;
toolStripLabel3.Enabled = false;
//toolStripButton3.Enabled = false; //toolStripButton3.Enabled = false;
//toolStripButton2.Enabled = false; //toolStripButton2.Enabled = false;
//btSave.Enabled = false; //btSave.Enabled = false;

View File

@@ -44,11 +44,17 @@ namespace FBS0000
this.dsReport.holydatasum.Clear(); this.dsReport.holydatasum.Clear();
var grp_user = dsReport.holydata.GroupBy(t => t.uid).ToList(); var grp_user = dsReport.holydata.GroupBy(t => t.uid).ToList();
int curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.holyday));
foreach (var grp in grp_user) foreach (var grp in grp_user)
{ {
//cate group //cate group
var first_user = grp.First(); var first_user = grp.First();
if (curLevel < 5 && grp.Key.Equals(FCOMMON.info.Login.no) == false)
{
continue;
}
var grp_cate = grp.GroupBy(t => t.cate).ToList(); var grp_cate = grp.GroupBy(t => t.cate).ToList();
foreach (var cate in grp_cate) foreach (var cate in grp_cate)
{ {

File diff suppressed because it is too large Load Diff

View File

@@ -20,32 +20,32 @@ WHERE (idx = @Original_idx)</CommandText>
</DbCommand> </DbCommand>
</DeleteCommand> </DeleteCommand>
<InsertCommand> <InsertCommand>
<DbCommand CommandType="Text" ModifiedByUser="true"> <DbCommand CommandType="Text" ModifiedByUser="false">
<CommandText>INSERT INTO EETGW_HolydayRequest <CommandText>INSERT INTO EETGW_HolydayRequest
(gcode, uid, cate, sdate, edate, conf, Remark, wuid, wdate, Response, HolyReason, HolyBackup, HolyLocation, HolyDays, HolyTimes, sendmail, stime, etime, conf_id, conf_time) (gcode, uid, cate, sdate, edate, conf, Remark, wuid, wdate, Response, HolyReason, HolyBackup, HolyLocation, HolyDays, HolyTimes, sendmail, stime, etime, conf_id, conf_time)
VALUES (@gcode,@uid,@cate,@sdate,@edate,@conf,@Remark,@wuid,@wdate,@Response,@HolyReason,@HolyBackup,@HolyLocation,@HolyDays,@HolyTimes,@sendmail,@stime,@etime,@conf_id,@conf_time); VALUES (@gcode,@uid,@cate,@sdate,@edate,@conf,@Remark,@wuid,@wdate,@Response,@HolyReason,@HolyBackup,@HolyLocation,@HolyDays,@HolyTimes,@sendmail,@stime,@etime,@conf_id,@conf_time);
SELECT idx, gcode, uid, cate, sdate, edate, conf, Remark, wuid, wdate FROM EETGW_HolydayRequest WHERE (idx = SCOPE_IDENTITY()) ORDER BY conf, sdate DESC</CommandText> SELECT idx, gcode, uid, cate, sdate, edate, conf, Remark, wuid, wdate FROM EETGW_HolydayRequest WHERE (idx = SCOPE_IDENTITY()) ORDER BY conf, sdate DESC</CommandText>
<Parameters> <Parameters>
<Parameter AllowDbNull="false" AutogeneratedName="gcode" ColumnName="gcode" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@gcode" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="gcode" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="false" AutogeneratedName="gcode" ColumnName="gcode" DataSourceName="" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@gcode" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="gcode" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="uid" ColumnName="uid" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@uid" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="uid" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="uid" ColumnName="uid" DataSourceName="" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@uid" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="uid" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="cate" ColumnName="cate" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@cate" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="cate" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="cate" ColumnName="cate" DataSourceName="" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@cate" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="cate" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="sdate" ColumnName="sdate" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@sdate" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="sdate" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="sdate" ColumnName="sdate" DataSourceName="" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@sdate" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="sdate" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="edate" ColumnName="edate" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@edate" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="edate" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="edate" ColumnName="edate" DataSourceName="" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@edate" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="edate" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="conf" ColumnName="conf" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="int" DbType="Int32" Direction="Input" ParameterName="@conf" Precision="0" ProviderType="Int" Scale="0" Size="4" SourceColumn="conf" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="conf" ColumnName="conf" DataSourceName="" DataTypeServer="int" DbType="Int32" Direction="Input" ParameterName="@conf" Precision="0" ProviderType="Int" Scale="0" Size="4" SourceColumn="conf" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="Remark" ColumnName="Remark" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(255)" DbType="AnsiString" Direction="Input" ParameterName="@Remark" Precision="0" ProviderType="VarChar" Scale="0" Size="255" SourceColumn="Remark" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="Remark" ColumnName="Remark" DataSourceName="" DataTypeServer="varchar(255)" DbType="AnsiString" Direction="Input" ParameterName="@Remark" Precision="0" ProviderType="VarChar" Scale="0" Size="255" SourceColumn="Remark" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="false" AutogeneratedName="wuid" ColumnName="wuid" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@wuid" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="wuid" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="false" AutogeneratedName="wuid" ColumnName="wuid" DataSourceName="" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@wuid" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="wuid" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="false" AutogeneratedName="wdate" ColumnName="wdate" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="smalldatetime" DbType="DateTime" Direction="Input" ParameterName="@wdate" Precision="0" ProviderType="SmallDateTime" Scale="0" Size="4" SourceColumn="wdate" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="false" AutogeneratedName="wdate" ColumnName="wdate" DataSourceName="" DataTypeServer="smalldatetime" DbType="DateTime" Direction="Input" ParameterName="@wdate" Precision="0" ProviderType="SmallDateTime" Scale="0" Size="4" SourceColumn="wdate" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="Response" ColumnName="Response" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(255)" DbType="AnsiString" Direction="Input" ParameterName="@Response" Precision="0" ProviderType="VarChar" Scale="0" Size="255" SourceColumn="Response" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="Response" ColumnName="Response" DataSourceName="" DataTypeServer="varchar(255)" DbType="AnsiString" Direction="Input" ParameterName="@Response" Precision="0" ProviderType="VarChar" Scale="0" Size="255" SourceColumn="Response" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="HolyReason" ColumnName="HolyReason" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(100)" DbType="AnsiString" Direction="Input" ParameterName="@HolyReason" Precision="0" ProviderType="VarChar" Scale="0" Size="100" SourceColumn="HolyReason" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="HolyReason" ColumnName="HolyReason" DataSourceName="" DataTypeServer="varchar(100)" DbType="AnsiString" Direction="Input" ParameterName="@HolyReason" Precision="0" ProviderType="VarChar" Scale="0" Size="100" SourceColumn="HolyReason" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="HolyBackup" ColumnName="HolyBackup" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(100)" DbType="AnsiString" Direction="Input" ParameterName="@HolyBackup" Precision="0" ProviderType="VarChar" Scale="0" Size="100" SourceColumn="HolyBackup" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="HolyBackup" ColumnName="HolyBackup" DataSourceName="" DataTypeServer="varchar(100)" DbType="AnsiString" Direction="Input" ParameterName="@HolyBackup" Precision="0" ProviderType="VarChar" Scale="0" Size="100" SourceColumn="HolyBackup" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="HolyLocation" ColumnName="HolyLocation" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(100)" DbType="AnsiString" Direction="Input" ParameterName="@HolyLocation" Precision="0" ProviderType="VarChar" Scale="0" Size="100" SourceColumn="HolyLocation" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="HolyLocation" ColumnName="HolyLocation" DataSourceName="" DataTypeServer="varchar(100)" DbType="AnsiString" Direction="Input" ParameterName="@HolyLocation" Precision="0" ProviderType="VarChar" Scale="0" Size="100" SourceColumn="HolyLocation" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="HolyDays" ColumnName="HolyDays" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="int" DbType="Double" Direction="Input" ParameterName="@HolyDays" Precision="0" ProviderType="Float" Scale="0" Size="8" SourceColumn="HolyDays" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="HolyDays" ColumnName="HolyDays" DataSourceName="" DataTypeServer="int" DbType="Double" Direction="Input" ParameterName="@HolyDays" Precision="0" ProviderType="Float" Scale="0" Size="8" SourceColumn="HolyDays" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="HolyTimes" ColumnName="HolyTimes" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="float" DbType="Double" Direction="Input" ParameterName="@HolyTimes" Precision="0" ProviderType="Float" Scale="0" Size="8" SourceColumn="HolyTimes" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="HolyTimes" ColumnName="HolyTimes" DataSourceName="" DataTypeServer="float" DbType="Double" Direction="Input" ParameterName="@HolyTimes" Precision="0" ProviderType="Float" Scale="0" Size="8" SourceColumn="HolyTimes" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="sendmail" ColumnName="sendmail" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="bit" DbType="Boolean" Direction="Input" ParameterName="@sendmail" Precision="0" ProviderType="Bit" Scale="0" Size="1" SourceColumn="sendmail" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="sendmail" ColumnName="sendmail" DataSourceName="" DataTypeServer="bit" DbType="Boolean" Direction="Input" ParameterName="@sendmail" Precision="0" ProviderType="Bit" Scale="0" Size="1" SourceColumn="sendmail" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="stime" ColumnName="stime" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@stime" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="stime" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="stime" ColumnName="stime" DataSourceName="" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@stime" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="stime" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="etime" ColumnName="etime" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@etime" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="etime" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="etime" ColumnName="etime" DataSourceName="" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@etime" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="etime" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="conf_id" ColumnName="conf_id" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@conf_id" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="conf_id" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="conf_id" ColumnName="conf_id" DataSourceName="" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@conf_id" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="conf_id" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="conf_time" ColumnName="conf_time" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="smalldatetime" DbType="DateTime" Direction="Input" ParameterName="@conf_time" Precision="0" ProviderType="SmallDateTime" Scale="0" Size="4" SourceColumn="conf_time" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="conf_time" ColumnName="conf_time" DataSourceName="" DataTypeServer="smalldatetime" DbType="DateTime" Direction="Input" ParameterName="@conf_time" Precision="0" ProviderType="SmallDateTime" Scale="0" Size="4" SourceColumn="conf_time" SourceColumnNullMapping="false" SourceVersion="Current" />
</Parameters> </Parameters>
</DbCommand> </DbCommand>
</InsertCommand> </InsertCommand>
@@ -58,17 +58,18 @@ SELECT idx, gcode, uid, cate, sdate, edate, conf, Remark, wuid, wdate FROM EETGW
EETGW_HolydayRequest.etime, EETGW_HolydayRequest.conf_id, EETGW_HolydayRequest.conf_time EETGW_HolydayRequest.etime, EETGW_HolydayRequest.conf_id, EETGW_HolydayRequest.conf_time
FROM EETGW_HolydayRequest WITH (nolock) LEFT OUTER JOIN FROM EETGW_HolydayRequest WITH (nolock) LEFT OUTER JOIN
vGroupUser ON EETGW_HolydayRequest.uid = vGroupUser.id AND EETGW_HolydayRequest.gcode = vGroupUser.gcode vGroupUser ON EETGW_HolydayRequest.uid = vGroupUser.id AND EETGW_HolydayRequest.gcode = vGroupUser.gcode
WHERE (EETGW_HolydayRequest.gcode = @gcode) AND (EETGW_HolydayRequest.sdate &gt;= @sd) AND (EETGW_HolydayRequest.sdate &lt;= @ed) WHERE (EETGW_HolydayRequest.gcode = @gcode) AND (EETGW_HolydayRequest.sdate &gt;= @sd) AND (EETGW_HolydayRequest.sdate &lt;= @ed) AND (EETGW_HolydayRequest.uid LIKE @uid)
ORDER BY EETGW_HolydayRequest.conf, EETGW_HolydayRequest.sdate DESC</CommandText> ORDER BY EETGW_HolydayRequest.conf, EETGW_HolydayRequest.sdate DESC</CommandText>
<Parameters> <Parameters>
<Parameter AllowDbNull="false" AutogeneratedName="gcode" ColumnName="gcode" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@gcode" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="gcode" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="false" AutogeneratedName="gcode" ColumnName="gcode" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@gcode" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="gcode" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="sd" ColumnName="sdate" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@sd" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="sdate" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="sd" ColumnName="sdate" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@sd" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="sdate" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="ed" ColumnName="sdate" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@ed" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="sdate" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="ed" ColumnName="sdate" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@ed" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="sdate" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="uid" ColumnName="uid" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@uid" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="uid" SourceColumnNullMapping="false" SourceVersion="Current" />
</Parameters> </Parameters>
</DbCommand> </DbCommand>
</SelectCommand> </SelectCommand>
<UpdateCommand> <UpdateCommand>
<DbCommand CommandType="Text" ModifiedByUser="true"> <DbCommand CommandType="Text" ModifiedByUser="false">
<CommandText>UPDATE EETGW_HolydayRequest <CommandText>UPDATE EETGW_HolydayRequest
SET gcode = @gcode, uid = @uid, cate = @cate, sdate = @sdate, edate = @edate, conf = @conf, Remark = @Remark, wuid = @wuid, wdate = @wdate, Response = @Response, SET gcode = @gcode, uid = @uid, cate = @cate, sdate = @sdate, edate = @edate, conf = @conf, Remark = @Remark, wuid = @wuid, wdate = @wdate, Response = @Response,
HolyReason = @HolyReason, HolyBackup = @HolyBackup, HolyLocation = @HolyLocation, HolyDays = @HolyDays, HolyTimes = @HolyTimes, sendmail = @sendmail, stime = @stime, HolyReason = @HolyReason, HolyBackup = @HolyBackup, HolyLocation = @HolyLocation, HolyDays = @HolyDays, HolyTimes = @HolyTimes, sendmail = @sendmail, stime = @stime,
@@ -76,28 +77,28 @@ SET gcode = @gcode, uid = @uid, cate = @cate, sdate = @sdate, edate = @ed
WHERE (idx = @Original_idx); WHERE (idx = @Original_idx);
SELECT idx, gcode, uid, cate, sdate, edate, conf, Remark, wuid, wdate FROM EETGW_HolydayRequest WHERE (idx = @idx) ORDER BY conf, sdate DESC</CommandText> SELECT idx, gcode, uid, cate, sdate, edate, conf, Remark, wuid, wdate FROM EETGW_HolydayRequest WHERE (idx = @idx) ORDER BY conf, sdate DESC</CommandText>
<Parameters> <Parameters>
<Parameter AllowDbNull="false" AutogeneratedName="gcode" ColumnName="gcode" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@gcode" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="gcode" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="false" AutogeneratedName="gcode" ColumnName="gcode" DataSourceName="" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@gcode" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="gcode" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="uid" ColumnName="uid" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@uid" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="uid" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="uid" ColumnName="uid" DataSourceName="" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@uid" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="uid" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="cate" ColumnName="cate" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@cate" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="cate" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="cate" ColumnName="cate" DataSourceName="" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@cate" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="cate" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="sdate" ColumnName="sdate" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@sdate" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="sdate" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="sdate" ColumnName="sdate" DataSourceName="" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@sdate" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="sdate" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="edate" ColumnName="edate" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@edate" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="edate" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="edate" ColumnName="edate" DataSourceName="" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@edate" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="edate" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="conf" ColumnName="conf" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="int" DbType="Int32" Direction="Input" ParameterName="@conf" Precision="0" ProviderType="Int" Scale="0" Size="4" SourceColumn="conf" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="conf" ColumnName="conf" DataSourceName="" DataTypeServer="int" DbType="Int32" Direction="Input" ParameterName="@conf" Precision="0" ProviderType="Int" Scale="0" Size="4" SourceColumn="conf" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="Remark" ColumnName="Remark" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(255)" DbType="AnsiString" Direction="Input" ParameterName="@Remark" Precision="0" ProviderType="VarChar" Scale="0" Size="255" SourceColumn="Remark" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="Remark" ColumnName="Remark" DataSourceName="" DataTypeServer="varchar(255)" DbType="AnsiString" Direction="Input" ParameterName="@Remark" Precision="0" ProviderType="VarChar" Scale="0" Size="255" SourceColumn="Remark" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="false" AutogeneratedName="wuid" ColumnName="wuid" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@wuid" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="wuid" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="false" AutogeneratedName="wuid" ColumnName="wuid" DataSourceName="" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@wuid" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="wuid" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="false" AutogeneratedName="wdate" ColumnName="wdate" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="smalldatetime" DbType="DateTime" Direction="Input" ParameterName="@wdate" Precision="0" ProviderType="SmallDateTime" Scale="0" Size="4" SourceColumn="wdate" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="false" AutogeneratedName="wdate" ColumnName="wdate" DataSourceName="" DataTypeServer="smalldatetime" DbType="DateTime" Direction="Input" ParameterName="@wdate" Precision="0" ProviderType="SmallDateTime" Scale="0" Size="4" SourceColumn="wdate" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="Response" ColumnName="Response" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(255)" DbType="AnsiString" Direction="Input" ParameterName="@Response" Precision="0" ProviderType="VarChar" Scale="0" Size="255" SourceColumn="Response" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="Response" ColumnName="Response" DataSourceName="" DataTypeServer="varchar(255)" DbType="AnsiString" Direction="Input" ParameterName="@Response" Precision="0" ProviderType="VarChar" Scale="0" Size="255" SourceColumn="Response" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="HolyReason" ColumnName="HolyReason" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(100)" DbType="AnsiString" Direction="Input" ParameterName="@HolyReason" Precision="0" ProviderType="VarChar" Scale="0" Size="100" SourceColumn="HolyReason" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="HolyReason" ColumnName="HolyReason" DataSourceName="" DataTypeServer="varchar(100)" DbType="AnsiString" Direction="Input" ParameterName="@HolyReason" Precision="0" ProviderType="VarChar" Scale="0" Size="100" SourceColumn="HolyReason" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="HolyBackup" ColumnName="HolyBackup" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(100)" DbType="AnsiString" Direction="Input" ParameterName="@HolyBackup" Precision="0" ProviderType="VarChar" Scale="0" Size="100" SourceColumn="HolyBackup" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="HolyBackup" ColumnName="HolyBackup" DataSourceName="" DataTypeServer="varchar(100)" DbType="AnsiString" Direction="Input" ParameterName="@HolyBackup" Precision="0" ProviderType="VarChar" Scale="0" Size="100" SourceColumn="HolyBackup" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="HolyLocation" ColumnName="HolyLocation" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(100)" DbType="AnsiString" Direction="Input" ParameterName="@HolyLocation" Precision="0" ProviderType="VarChar" Scale="0" Size="100" SourceColumn="HolyLocation" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="HolyLocation" ColumnName="HolyLocation" DataSourceName="" DataTypeServer="varchar(100)" DbType="AnsiString" Direction="Input" ParameterName="@HolyLocation" Precision="0" ProviderType="VarChar" Scale="0" Size="100" SourceColumn="HolyLocation" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="HolyDays" ColumnName="HolyDays" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="int" DbType="Double" Direction="Input" ParameterName="@HolyDays" Precision="0" ProviderType="Float" Scale="0" Size="8" SourceColumn="HolyDays" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="HolyDays" ColumnName="HolyDays" DataSourceName="" DataTypeServer="int" DbType="Double" Direction="Input" ParameterName="@HolyDays" Precision="0" ProviderType="Float" Scale="0" Size="8" SourceColumn="HolyDays" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="HolyTimes" ColumnName="HolyTimes" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="float" DbType="Double" Direction="Input" ParameterName="@HolyTimes" Precision="0" ProviderType="Float" Scale="0" Size="8" SourceColumn="HolyTimes" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="HolyTimes" ColumnName="HolyTimes" DataSourceName="" DataTypeServer="float" DbType="Double" Direction="Input" ParameterName="@HolyTimes" Precision="0" ProviderType="Float" Scale="0" Size="8" SourceColumn="HolyTimes" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="sendmail" ColumnName="sendmail" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="bit" DbType="Boolean" Direction="Input" ParameterName="@sendmail" Precision="0" ProviderType="Bit" Scale="0" Size="1" SourceColumn="sendmail" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="sendmail" ColumnName="sendmail" DataSourceName="" DataTypeServer="bit" DbType="Boolean" Direction="Input" ParameterName="@sendmail" Precision="0" ProviderType="Bit" Scale="0" Size="1" SourceColumn="sendmail" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="stime" ColumnName="stime" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@stime" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="stime" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="stime" ColumnName="stime" DataSourceName="" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@stime" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="stime" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="etime" ColumnName="etime" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@etime" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="etime" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="etime" ColumnName="etime" DataSourceName="" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@etime" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="etime" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="conf_id" ColumnName="conf_id" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@conf_id" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="conf_id" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="conf_id" ColumnName="conf_id" DataSourceName="" DataTypeServer="varchar(20)" DbType="AnsiString" Direction="Input" ParameterName="@conf_id" Precision="0" ProviderType="VarChar" Scale="0" Size="20" SourceColumn="conf_id" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="conf_time" ColumnName="conf_time" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="smalldatetime" DbType="DateTime" Direction="Input" ParameterName="@conf_time" Precision="0" ProviderType="SmallDateTime" Scale="0" Size="4" SourceColumn="conf_time" SourceColumnNullMapping="false" SourceVersion="Current" /> <Parameter AllowDbNull="true" AutogeneratedName="conf_time" ColumnName="conf_time" DataSourceName="" DataTypeServer="smalldatetime" DbType="DateTime" Direction="Input" ParameterName="@conf_time" Precision="0" ProviderType="SmallDateTime" Scale="0" Size="4" SourceColumn="conf_time" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="false" AutogeneratedName="Original_idx" ColumnName="idx" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="int" DbType="Int32" Direction="Input" ParameterName="@Original_idx" Precision="0" ProviderType="Int" Scale="0" Size="4" SourceColumn="idx" SourceColumnNullMapping="false" SourceVersion="Original" /> <Parameter AllowDbNull="false" AutogeneratedName="Original_idx" ColumnName="idx" DataSourceName="" DataTypeServer="int" DbType="Int32" Direction="Input" ParameterName="@Original_idx" Precision="0" ProviderType="Int" Scale="0" Size="4" SourceColumn="idx" SourceColumnNullMapping="false" SourceVersion="Original" />
<Parameter AllowDbNull="false" AutogeneratedName="idx" ColumnName="idx" DataSourceName="EE.dbo.EETGW_HolydayRequest" DataTypeServer="int" DbType="Int32" Direction="Input" ParameterName="@idx" Precision="0" ProviderType="Int" Scale="0" Size="4" SourceColumn="idx" SourceColumnNullMapping="false" SourceVersion="Original" /> <Parameter AllowDbNull="false" AutogeneratedName="idx" ColumnName="idx" DataSourceName="" DataTypeServer="int" DbType="Int32" Direction="Input" ParameterName="@idx" Precision="0" ProviderType="Int" Scale="0" Size="4" SourceColumn="idx" SourceColumnNullMapping="false" SourceVersion="Original" />
</Parameters> </Parameters>
</DbCommand> </DbCommand>
</UpdateCommand> </UpdateCommand>
@@ -138,152 +139,152 @@ SELECT idx, gcode, uid, cate, sdate, edate, conf, Remark, wuid, wdate FROM EETGW
</DataSource> </DataSource>
</xs:appinfo> </xs:appinfo>
</xs:annotation> </xs:annotation>
<xs:element name="DSKuntae" msdata:IsDataSet="true" msdata:UseCurrentLocale="true" msprop:Generator_UserDSName="DSKuntae" msprop:EnableTableAdapterManager="true" msprop:Generator_DataSetName="DSKuntae"> <xs:element name="DSKuntae" msdata:IsDataSet="true" msdata:UseCurrentLocale="true" msprop:EnableTableAdapterManager="true" msprop:Generator_DataSetName="DSKuntae" msprop:Generator_UserDSName="DSKuntae">
<xs:complexType> <xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="EETGW_HolydayRequest" msprop:Generator_RowEvHandlerName="EETGW_HolydayRequestRowChangeEventHandler" msprop:Generator_RowDeletedName="EETGW_HolydayRequestRowDeleted" msprop:Generator_RowDeletingName="EETGW_HolydayRequestRowDeleting" msprop:Generator_RowEvArgName="EETGW_HolydayRequestRowChangeEvent" msprop:Generator_TablePropName="EETGW_HolydayRequest" msprop:Generator_RowChangedName="EETGW_HolydayRequestRowChanged" msprop:Generator_UserTableName="EETGW_HolydayRequest" msprop:Generator_RowChangingName="EETGW_HolydayRequestRowChanging" msprop:Generator_RowClassName="EETGW_HolydayRequestRow" msprop:Generator_TableClassName="EETGW_HolydayRequestDataTable" msprop:Generator_TableVarName="tableEETGW_HolydayRequest"> <xs:element name="EETGW_HolydayRequest" msprop:Generator_UserTableName="EETGW_HolydayRequest" msprop:Generator_RowEvArgName="EETGW_HolydayRequestRowChangeEvent" msprop:Generator_TableVarName="tableEETGW_HolydayRequest" msprop:Generator_TablePropName="EETGW_HolydayRequest" msprop:Generator_RowDeletingName="EETGW_HolydayRequestRowDeleting" msprop:Generator_RowChangingName="EETGW_HolydayRequestRowChanging" msprop:Generator_RowDeletedName="EETGW_HolydayRequestRowDeleted" msprop:Generator_RowEvHandlerName="EETGW_HolydayRequestRowChangeEventHandler" msprop:Generator_TableClassName="EETGW_HolydayRequestDataTable" msprop:Generator_RowChangedName="EETGW_HolydayRequestRowChanged" msprop:Generator_RowClassName="EETGW_HolydayRequestRow">
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:sequence>
<xs:element name="idx" msdata:ReadOnly="true" msdata:AutoIncrement="true" msdata:AutoIncrementSeed="-1" msdata:AutoIncrementStep="-1" msprop:Generator_ColumnPropNameInTable="idxColumn" msprop:Generator_ColumnPropNameInRow="idx" msprop:Generator_UserColumnName="idx" msprop:Generator_ColumnVarNameInTable="columnidx" type="xs:int" /> <xs:element name="idx" msdata:ReadOnly="true" msdata:AutoIncrement="true" msdata:AutoIncrementSeed="-1" msdata:AutoIncrementStep="-1" msprop:Generator_ColumnVarNameInTable="columnidx" msprop:Generator_ColumnPropNameInRow="idx" msprop:Generator_ColumnPropNameInTable="idxColumn" msprop:Generator_UserColumnName="idx" type="xs:int" />
<xs:element name="gcode" msprop:Generator_ColumnPropNameInTable="gcodeColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="gcode" msprop:Generator_UserColumnName="gcode" msprop:Generator_ColumnVarNameInTable="columngcode"> <xs:element name="gcode" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="gcode" msprop:Generator_ColumnVarNameInTable="columngcode" msprop:Generator_ColumnPropNameInTable="gcodeColumn" msprop:Generator_UserColumnName="gcode">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="10" /> <xs:maxLength value="10" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="uid" msprop:Generator_ColumnPropNameInTable="uidColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="uid" msprop:Generator_UserColumnName="uid" msprop:Generator_ColumnVarNameInTable="columnuid" minOccurs="0"> <xs:element name="uid" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="uid" msprop:Generator_ColumnVarNameInTable="columnuid" msprop:Generator_ColumnPropNameInTable="uidColumn" msprop:Generator_UserColumnName="uid" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="20" /> <xs:maxLength value="20" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="cate" msprop:Generator_ColumnPropNameInTable="cateColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="cate" msprop:Generator_UserColumnName="cate" msprop:Generator_ColumnVarNameInTable="columncate" minOccurs="0"> <xs:element name="cate" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="cate" msprop:Generator_ColumnVarNameInTable="columncate" msprop:Generator_ColumnPropNameInTable="cateColumn" msprop:Generator_UserColumnName="cate" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="20" /> <xs:maxLength value="20" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="sdate" msprop:Generator_ColumnPropNameInTable="sdateColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="sdate" msprop:Generator_UserColumnName="sdate" msprop:Generator_ColumnVarNameInTable="columnsdate" minOccurs="0"> <xs:element name="sdate" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="sdate" msprop:Generator_ColumnVarNameInTable="columnsdate" msprop:Generator_ColumnPropNameInTable="sdateColumn" msprop:Generator_UserColumnName="sdate" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="10" /> <xs:maxLength value="10" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="edate" msprop:Generator_ColumnPropNameInTable="edateColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="edate" msprop:Generator_UserColumnName="edate" msprop:Generator_ColumnVarNameInTable="columnedate" minOccurs="0"> <xs:element name="edate" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="edate" msprop:Generator_ColumnVarNameInTable="columnedate" msprop:Generator_ColumnPropNameInTable="edateColumn" msprop:Generator_UserColumnName="edate" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="10" /> <xs:maxLength value="10" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="Remark" msprop:Generator_ColumnPropNameInTable="RemarkColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="Remark" msprop:Generator_UserColumnName="Remark" msprop:Generator_ColumnVarNameInTable="columnRemark" minOccurs="0"> <xs:element name="Remark" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="Remark" msprop:Generator_ColumnVarNameInTable="columnRemark" msprop:Generator_ColumnPropNameInTable="RemarkColumn" msprop:Generator_UserColumnName="Remark" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="255" /> <xs:maxLength value="255" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="wuid" msprop:Generator_ColumnPropNameInTable="wuidColumn" msprop:Generator_ColumnPropNameInRow="wuid" msprop:Generator_UserColumnName="wuid" msprop:Generator_ColumnVarNameInTable="columnwuid"> <xs:element name="wuid" msprop:Generator_ColumnVarNameInTable="columnwuid" msprop:Generator_ColumnPropNameInRow="wuid" msprop:Generator_ColumnPropNameInTable="wuidColumn" msprop:Generator_UserColumnName="wuid">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="20" /> <xs:maxLength value="20" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="wdate" msprop:Generator_ColumnPropNameInTable="wdateColumn" msprop:Generator_ColumnPropNameInRow="wdate" msprop:Generator_UserColumnName="wdate" msprop:Generator_ColumnVarNameInTable="columnwdate" type="xs:dateTime" /> <xs:element name="wdate" msprop:Generator_ColumnVarNameInTable="columnwdate" msprop:Generator_ColumnPropNameInRow="wdate" msprop:Generator_ColumnPropNameInTable="wdateColumn" msprop:Generator_UserColumnName="wdate" type="xs:dateTime" />
<xs:element name="dept" msprop:Generator_ColumnPropNameInTable="deptColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="dept" msprop:Generator_UserColumnName="dept" msprop:Generator_ColumnVarNameInTable="columndept" minOccurs="0"> <xs:element name="dept" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="dept" msprop:Generator_ColumnVarNameInTable="columndept" msprop:Generator_ColumnPropNameInTable="deptColumn" msprop:Generator_UserColumnName="dept" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="100" /> <xs:maxLength value="100" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="name" msprop:Generator_ColumnPropNameInTable="nameColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="name" msprop:Generator_UserColumnName="name" msprop:Generator_ColumnVarNameInTable="columnname" minOccurs="0"> <xs:element name="name" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="name" msprop:Generator_ColumnVarNameInTable="columnname" msprop:Generator_ColumnPropNameInTable="nameColumn" msprop:Generator_UserColumnName="name" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="100" /> <xs:maxLength value="100" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="grade" msprop:Generator_ColumnPropNameInTable="gradeColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="grade" msprop:Generator_UserColumnName="grade" msprop:Generator_ColumnVarNameInTable="columngrade" minOccurs="0"> <xs:element name="grade" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="grade" msprop:Generator_ColumnVarNameInTable="columngrade" msprop:Generator_ColumnPropNameInTable="gradeColumn" msprop:Generator_UserColumnName="grade" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="10" /> <xs:maxLength value="10" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="tel" msprop:Generator_ColumnPropNameInTable="telColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="tel" msprop:Generator_UserColumnName="tel" msprop:Generator_ColumnVarNameInTable="columntel" minOccurs="0"> <xs:element name="tel" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="tel" msprop:Generator_ColumnVarNameInTable="columntel" msprop:Generator_ColumnPropNameInTable="telColumn" msprop:Generator_UserColumnName="tel" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="20" /> <xs:maxLength value="20" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="processs" msdata:ReadOnly="true" msprop:Generator_ColumnPropNameInTable="processsColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="processs" msprop:Generator_UserColumnName="processs" msprop:Generator_ColumnVarNameInTable="columnprocesss" minOccurs="0"> <xs:element name="processs" msdata:ReadOnly="true" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="processs" msprop:Generator_ColumnVarNameInTable="columnprocesss" msprop:Generator_ColumnPropNameInTable="processsColumn" msprop:Generator_UserColumnName="processs" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="50" /> <xs:maxLength value="50" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="Response" msprop:Generator_ColumnPropNameInTable="ResponseColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="Response" msprop:Generator_UserColumnName="Response" msprop:Generator_ColumnVarNameInTable="columnResponse" minOccurs="0"> <xs:element name="Response" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="Response" msprop:Generator_ColumnVarNameInTable="columnResponse" msprop:Generator_ColumnPropNameInTable="ResponseColumn" msprop:Generator_UserColumnName="Response" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="255" /> <xs:maxLength value="255" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="conf" msprop:Generator_ColumnPropNameInTable="confColumn" msprop:nullValue="0" msprop:Generator_ColumnPropNameInRow="conf" msprop:Generator_UserColumnName="conf" msprop:Generator_ColumnVarNameInTable="columnconf" type="xs:int" minOccurs="0" /> <xs:element name="conf" msprop:nullValue="0" msprop:Generator_ColumnPropNameInRow="conf" msprop:Generator_ColumnVarNameInTable="columnconf" msprop:Generator_ColumnPropNameInTable="confColumn" msprop:Generator_UserColumnName="conf" type="xs:int" minOccurs="0" />
<xs:element name="HolyReason" msprop:Generator_ColumnPropNameInTable="HolyReasonColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="HolyReason" msprop:Generator_UserColumnName="HolyReason" msprop:Generator_ColumnVarNameInTable="columnHolyReason" minOccurs="0"> <xs:element name="HolyReason" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="HolyReason" msprop:Generator_ColumnVarNameInTable="columnHolyReason" msprop:Generator_ColumnPropNameInTable="HolyReasonColumn" msprop:Generator_UserColumnName="HolyReason" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="100" /> <xs:maxLength value="100" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="HolyBackup" msprop:Generator_ColumnPropNameInTable="HolyBackupColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="HolyBackup" msprop:Generator_UserColumnName="HolyBackup" msprop:Generator_ColumnVarNameInTable="columnHolyBackup" minOccurs="0"> <xs:element name="HolyBackup" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="HolyBackup" msprop:Generator_ColumnVarNameInTable="columnHolyBackup" msprop:Generator_ColumnPropNameInTable="HolyBackupColumn" msprop:Generator_UserColumnName="HolyBackup" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="100" /> <xs:maxLength value="100" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="HolyLocation" msprop:Generator_ColumnPropNameInTable="HolyLocationColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="HolyLocation" msprop:Generator_UserColumnName="HolyLocation" msprop:Generator_ColumnVarNameInTable="columnHolyLocation" minOccurs="0"> <xs:element name="HolyLocation" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="HolyLocation" msprop:Generator_ColumnVarNameInTable="columnHolyLocation" msprop:Generator_ColumnPropNameInTable="HolyLocationColumn" msprop:Generator_UserColumnName="HolyLocation" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="100" /> <xs:maxLength value="100" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="HolyDays" msprop:Generator_ColumnPropNameInTable="HolyDaysColumn" msprop:nullValue="0" msprop:Generator_ColumnPropNameInRow="HolyDays" msprop:Generator_UserColumnName="HolyDays" msprop:Generator_ColumnVarNameInTable="columnHolyDays" type="xs:double" minOccurs="0" /> <xs:element name="HolyDays" msprop:nullValue="0" msprop:Generator_ColumnPropNameInRow="HolyDays" msprop:Generator_ColumnVarNameInTable="columnHolyDays" msprop:Generator_ColumnPropNameInTable="HolyDaysColumn" msprop:Generator_UserColumnName="HolyDays" type="xs:double" minOccurs="0" />
<xs:element name="HolyTimes" msprop:Generator_ColumnPropNameInTable="HolyTimesColumn" msprop:nullValue="0" msprop:Generator_ColumnPropNameInRow="HolyTimes" msprop:Generator_UserColumnName="HolyTimes" msprop:Generator_ColumnVarNameInTable="columnHolyTimes" type="xs:double" minOccurs="0" /> <xs:element name="HolyTimes" msprop:nullValue="0" msprop:Generator_ColumnPropNameInRow="HolyTimes" msprop:Generator_ColumnVarNameInTable="columnHolyTimes" msprop:Generator_ColumnPropNameInTable="HolyTimesColumn" msprop:Generator_UserColumnName="HolyTimes" type="xs:double" minOccurs="0" />
<xs:element name="sendmail" msprop:Generator_ColumnPropNameInTable="sendmailColumn" msprop:nullValue="0" msprop:Generator_ColumnPropNameInRow="sendmail" msprop:Generator_UserColumnName="sendmail" msprop:Generator_ColumnVarNameInTable="columnsendmail" type="xs:boolean" minOccurs="0" /> <xs:element name="sendmail" msprop:nullValue="0" msprop:Generator_ColumnPropNameInRow="sendmail" msprop:Generator_ColumnVarNameInTable="columnsendmail" msprop:Generator_ColumnPropNameInTable="sendmailColumn" msprop:Generator_UserColumnName="sendmail" type="xs:boolean" minOccurs="0" />
<xs:element name="stime" msprop:Generator_ColumnPropNameInTable="stimeColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="stime" msprop:Generator_UserColumnName="stime" msprop:Generator_ColumnVarNameInTable="columnstime" minOccurs="0"> <xs:element name="stime" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="stime" msprop:Generator_ColumnVarNameInTable="columnstime" msprop:Generator_ColumnPropNameInTable="stimeColumn" msprop:Generator_UserColumnName="stime" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="10" /> <xs:maxLength value="10" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="etime" msprop:Generator_ColumnPropNameInTable="etimeColumn" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="etime" msprop:Generator_UserColumnName="etime" msprop:Generator_ColumnVarNameInTable="columnetime" minOccurs="0"> <xs:element name="etime" msprop:nullValue="_empty" msprop:Generator_ColumnPropNameInRow="etime" msprop:Generator_ColumnVarNameInTable="columnetime" msprop:Generator_ColumnPropNameInTable="etimeColumn" msprop:Generator_UserColumnName="etime" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="10" /> <xs:maxLength value="10" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="conf_id" msprop:Generator_ColumnPropNameInTable="conf_idColumn" msprop:Generator_ColumnPropNameInRow="conf_id" msprop:Generator_UserColumnName="conf_id" msprop:Generator_ColumnVarNameInTable="columnconf_id" minOccurs="0"> <xs:element name="conf_id" msprop:Generator_ColumnVarNameInTable="columnconf_id" msprop:Generator_ColumnPropNameInRow="conf_id" msprop:Generator_ColumnPropNameInTable="conf_idColumn" msprop:Generator_UserColumnName="conf_id" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="20" /> <xs:maxLength value="20" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="conf_time" msprop:Generator_ColumnPropNameInTable="conf_timeColumn" msprop:Generator_ColumnPropNameInRow="conf_time" msprop:Generator_UserColumnName="conf_time" msprop:Generator_ColumnVarNameInTable="columnconf_time" type="xs:dateTime" minOccurs="0" /> <xs:element name="conf_time" msprop:Generator_ColumnVarNameInTable="columnconf_time" msprop:Generator_ColumnPropNameInRow="conf_time" msprop:Generator_ColumnPropNameInTable="conf_timeColumn" msprop:Generator_UserColumnName="conf_time" type="xs:dateTime" minOccurs="0" />
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>

View File

@@ -4,7 +4,7 @@
Changes to this file may cause incorrect behavior and will be lost if Changes to this file may cause incorrect behavior and will be lost if
the code is regenerated. the code is regenerated.
</autogenerated>--> </autogenerated>-->
<DiagramLayout xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ex:showrelationlabel="False" ViewPortX="385" ViewPortY="0" xmlns:ex="urn:schemas-microsoft-com:xml-msdatasource-layout-extended" xmlns="urn:schemas-microsoft-com:xml-msdatasource-layout"> <DiagramLayout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ex:showrelationlabel="False" ViewPortX="385" ViewPortY="0" xmlns:ex="urn:schemas-microsoft-com:xml-msdatasource-layout-extended" xmlns="urn:schemas-microsoft-com:xml-msdatasource-layout">
<Shapes> <Shapes>
<Shape ID="DesignTable:EETGW_HolydayRequest" ZOrder="1" X="543" Y="76" Height="476" Width="287" AdapterExpanded="true" DataTableExpanded="true" OldAdapterHeight="0" OldDataTableHeight="0" SplitterPosition="425" /> <Shape ID="DesignTable:EETGW_HolydayRequest" ZOrder="1" X="543" Y="76" Height="476" Width="287" AdapterExpanded="true" DataTableExpanded="true" OldAdapterHeight="0" OldDataTableHeight="0" SplitterPosition="425" />
</Shapes> </Shapes>

View File

@@ -38,7 +38,7 @@
this.dte = new System.Windows.Forms.DateTimePicker(); this.dte = new System.Windows.Forms.DateTimePicker();
this.label2 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label();
this.dts = new System.Windows.Forms.DateTimePicker(); this.dts = new System.Windows.Forms.DateTimePicker();
this.tbProcess = new System.Windows.Forms.ComboBox(); this.cmbProcess = new System.Windows.Forms.ComboBox();
this.label1 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label();
this.btRefresh = new System.Windows.Forms.Button(); this.btRefresh = new System.Windows.Forms.Button();
this.fpSpread1 = new FarPoint.Win.Spread.FpSpread(); this.fpSpread1 = new FarPoint.Win.Spread.FpSpread();
@@ -61,7 +61,7 @@
this.panel1.Controls.Add(this.dte); this.panel1.Controls.Add(this.dte);
this.panel1.Controls.Add(this.label2); this.panel1.Controls.Add(this.label2);
this.panel1.Controls.Add(this.dts); this.panel1.Controls.Add(this.dts);
this.panel1.Controls.Add(this.tbProcess); this.panel1.Controls.Add(this.cmbProcess);
this.panel1.Controls.Add(this.label1); this.panel1.Controls.Add(this.label1);
this.panel1.Controls.Add(this.btRefresh); this.panel1.Controls.Add(this.btRefresh);
this.panel1.Dock = System.Windows.Forms.DockStyle.Top; this.panel1.Dock = System.Windows.Forms.DockStyle.Top;
@@ -157,13 +157,13 @@
// //
// tbProcess // tbProcess
// //
this.tbProcess.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cmbProcess.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.tbProcess.FormattingEnabled = true; this.cmbProcess.FormattingEnabled = true;
this.tbProcess.Location = new System.Drawing.Point(68, 32); this.cmbProcess.Location = new System.Drawing.Point(68, 32);
this.tbProcess.Name = "tbProcess"; this.cmbProcess.Name = "tbProcess";
this.tbProcess.Size = new System.Drawing.Size(180, 20); this.cmbProcess.Size = new System.Drawing.Size(180, 20);
this.tbProcess.TabIndex = 5; this.cmbProcess.TabIndex = 5;
this.tbProcess.SelectedIndexChanged += new System.EventHandler(this.tbProcess_SelectedIndexChanged); this.cmbProcess.SelectedIndexChanged += new System.EventHandler(this.tbProcess_SelectedIndexChanged);
// //
// label1 // label1
// //
@@ -239,7 +239,7 @@
private System.Windows.Forms.DateTimePicker dte; private System.Windows.Forms.DateTimePicker dte;
private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label2;
private System.Windows.Forms.DateTimePicker dts; private System.Windows.Forms.DateTimePicker dts;
private System.Windows.Forms.ComboBox tbProcess; private System.Windows.Forms.ComboBox cmbProcess;
private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button btRefresh; private System.Windows.Forms.Button btRefresh;
private FarPoint.Win.Spread.FpSpread fpSpread1; private FarPoint.Win.Spread.FpSpread fpSpread1;

View File

@@ -14,7 +14,7 @@ namespace FPJ0000.JobReport_
public partial class fJobChartMenu : fBase public partial class fJobChartMenu : fBase
{ {
Boolean binit = false; Boolean binit = false;
int curLevel = 0;// Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
public fJobChartMenu() public fJobChartMenu()
{ {
InitializeComponent(); InitializeComponent();
@@ -22,7 +22,7 @@ namespace FPJ0000.JobReport_
Properties.Settings.Default["gwcs"] = FCOMMON.info.CS; Properties.Settings.Default["gwcs"] = FCOMMON.info.CS;
Properties.Settings.Default["EEEntities"] = FCOMMON.info.CS; Properties.Settings.Default["EEEntities"] = FCOMMON.info.CS;
Properties.Settings.Default["EEEntitiesLayout"] = FCOMMON.info.CS; Properties.Settings.Default["EEEntitiesLayout"] = FCOMMON.info.CS;
curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
this.dts.Value = DateTime.Parse(DateTime.Now.AddMonths(-1).ToString("yyyy-MM-01")); this.dts.Value = DateTime.Parse(DateTime.Now.AddMonths(-1).ToString("yyyy-MM-01"));
this.dte.Value = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-01")).AddDays(-1); this.dte.Value = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-01")).AddDays(-1);
@@ -30,19 +30,19 @@ namespace FPJ0000.JobReport_
private void fJobChartMenu_Load(object sender, EventArgs e) private void fJobChartMenu_Load(object sender, EventArgs e)
{ {
EnsureVisibleAndUsableSize(); EnsureVisibleAndUsableSize();
this.tbProcess.Items.Clear(); this.cmbProcess.Items.Clear();
tbProcess.Items.Add("--전체--"); cmbProcess.Items.Add("--전체--");
// var taProcess = new dsReportTableAdapters.ProcessListTableAdapter(); // var taProcess = new dsReportTableAdapters.ProcessListTableAdapter();
var dtProcessList = FCOMMON.DBM.GroupUserProcessList();// taProcess.GetData(FCOMMON.info.Login.gcode); var dtProcessList = FCOMMON.DBM.GroupUserProcessList();// taProcess.GetData(FCOMMON.info.Login.gcode);
foreach (var dr in dtProcessList) foreach (var dr in dtProcessList)
tbProcess.Items.Add(dr); cmbProcess.Items.Add(dr);
//사용자의 공정명을 선택해준다 //사용자의 공정명을 선택해준다
this.tbProcess.Text = FCOMMON.info.Login.process; this.cmbProcess.Text = FCOMMON.info.Login.process;
//프로세스가 선택되지 않았다면 전체를 선택해준다. //프로세스가 선택되지 않았다면 전체를 선택해준다.
if (tbProcess.SelectedIndex < 0) tbProcess.SelectedIndex = 0; if (cmbProcess.SelectedIndex < 0) cmbProcess.SelectedIndex = 0;
//사용자 목록을 선택한다 //사용자 목록을 선택한다
UpdateUserList(); UpdateUserList();
@@ -59,6 +59,12 @@ namespace FPJ0000.JobReport_
binit = true; binit = true;
btSave.Enabled = true; btSave.Enabled = true;
btRefresh.Enabled = true; btRefresh.Enabled = true;
if(curLevel < 5)
{
this.cmbProcess.Enabled = false;
cmbUser.Enabled = false;
}
} }
void UpdateUserList() void UpdateUserList()
{ {
@@ -80,7 +86,7 @@ namespace FPJ0000.JobReport_
var id = item.Field<string>("id"); var id = item.Field<string>("id");
var dispname = item.Field<string>("dispname"); var dispname = item.Field<string>("dispname");
var process = item.Field<string>("process"); var process = item.Field<string>("process");
if (tbProcess.SelectedIndex > 0 && tbProcess.Text.Equals(process) == false) continue; if (cmbProcess.SelectedIndex > 0 && cmbProcess.Text.Equals(process) == false) continue;
cmbUser.Items.Add(dispname); cmbUser.Items.Add(dispname);
} }
@@ -96,7 +102,7 @@ namespace FPJ0000.JobReport_
////if (tbProcess.SelectedIndex != 0) userlist = userlist.Where(t => t.processs == tbProcess.Text); //해당 공정의 인원만 처리한다 ////if (tbProcess.SelectedIndex != 0) userlist = userlist.Where(t => t.processs == tbProcess.Text); //해당 공정의 인원만 처리한다
if (tbProcess.SelectedIndex > 0) if (cmbProcess.SelectedIndex > 0)
cmbUser.Text = string.Format("{1}({0})", FCOMMON.info.Login.no, FCOMMON.info.Login.nameK); cmbUser.Text = string.Format("{1}({0})", FCOMMON.info.Login.no, FCOMMON.info.Login.nameK);
if (cmbUser.SelectedIndex < 0) cmbUser.SelectedIndex = 0; //기본전체로 선택해준다. if (cmbUser.SelectedIndex < 0) cmbUser.SelectedIndex = 0; //기본전체로 선택해준다.
@@ -120,7 +126,7 @@ namespace FPJ0000.JobReport_
fpSpread1.Visible = false; fpSpread1.Visible = false;
//조회공정 //조회공정
this.fpSpread1.Sheets[0].Cells[3, 2].Value = tbProcess.Text; this.fpSpread1.Sheets[0].Cells[3, 2].Value = cmbProcess.Text;
//담당자 //담당자
this.fpSpread1.Sheets[0].Cells[3, 3].Value = cmbUser.Text; this.fpSpread1.Sheets[0].Cells[3, 3].Value = cmbUser.Text;
@@ -159,9 +165,9 @@ namespace FPJ0000.JobReport_
var UserNo = getUserID();// cmbUser.Text.Substring(1, cmbUser.Text.IndexOf(']') - 1); var UserNo = getUserID();// cmbUser.Text.Substring(1, cmbUser.Text.IndexOf(']') - 1);
userCount = 1;// db.vJobReportForUser.Where(t => t.gcode == FCOMMON.info.Login.gcode && t.id == UserNo).GroupBy(t=>t.id).Count(); userCount = 1;// db.vJobReportForUser.Where(t => t.gcode == FCOMMON.info.Login.gcode && t.id == UserNo).GroupBy(t=>t.id).Count();
} }
else if (tbProcess.SelectedIndex > 0) else if (cmbProcess.SelectedIndex > 0)
{ {
userCount = (int)taJobreportuser.GetProcessUserCount(FCOMMON.info.Login.gcode,tbProcess.Text);// db.vJobReportForUser.Where(t => t.gcode == FCOMMON.info.Login.gcode && t.userProcess == tbProcess.Text).GroupBy(t => t.id).Count(); userCount = (int)taJobreportuser.GetProcessUserCount(FCOMMON.info.Login.gcode,cmbProcess.Text);// db.vJobReportForUser.Where(t => t.gcode == FCOMMON.info.Login.gcode && t.userProcess == tbProcess.Text).GroupBy(t => t.id).Count();
} }
else else
{ {
@@ -188,9 +194,9 @@ namespace FPJ0000.JobReport_
//.OrderBy(t => t.pdate) //.OrderBy(t => t.pdate)
//.ToList(); //.ToList();
} }
else if (tbProcess.SelectedIndex > 0) else if (cmbProcess.SelectedIndex > 0)
{ {
baseData = taJobreportuser.GetByProcess(FCOMMON.info.Login.gcode, tbProcess.Text, vSD, vED);// db.vJobReportForUser baseData = taJobreportuser.GetByProcess(FCOMMON.info.Login.gcode, cmbProcess.Text, vSD, vED);// db.vJobReportForUser
//.Where(t => t.gcode == FCOMMON.info.Login.gcode && t.pdate.CompareTo(vSD) >= 0 && t.pdate.CompareTo(vED) <= 0 && t.userProcess == tbProcess.Text) //.Where(t => t.gcode == FCOMMON.info.Login.gcode && t.pdate.CompareTo(vSD) >= 0 && t.pdate.CompareTo(vED) <= 0 && t.userProcess == tbProcess.Text)
//.OrderBy(t => t.name) //.OrderBy(t => t.name)
//.OrderBy(t => t.pdate) //.OrderBy(t => t.pdate)

View File

@@ -30,27 +30,27 @@
{ {
this.components = new System.ComponentModel.Container(); this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(fJobReport)); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(fJobReport));
FarPoint.Win.Spread.CellType.TextCellType textCellType1 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType15 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.TextCellType textCellType2 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType16 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.TextCellType textCellType3 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType17 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.TextCellType textCellType4 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType18 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.TextCellType textCellType5 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType19 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.TextCellType textCellType6 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType20 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.TextCellType textCellType7 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType21 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.TextCellType textCellType8 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType22 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.TextCellType textCellType9 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType23 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.TextCellType textCellType10 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType24 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.NumberCellType numberCellType1 = new FarPoint.Win.Spread.CellType.NumberCellType(); FarPoint.Win.Spread.CellType.NumberCellType numberCellType6 = new FarPoint.Win.Spread.CellType.NumberCellType();
FarPoint.Win.Spread.CellType.NumberCellType numberCellType2 = new FarPoint.Win.Spread.CellType.NumberCellType(); FarPoint.Win.Spread.CellType.NumberCellType numberCellType7 = new FarPoint.Win.Spread.CellType.NumberCellType();
FarPoint.Win.Spread.CellType.NumberCellType numberCellType3 = new FarPoint.Win.Spread.CellType.NumberCellType(); FarPoint.Win.Spread.CellType.NumberCellType numberCellType8 = new FarPoint.Win.Spread.CellType.NumberCellType();
FarPoint.Win.Spread.CellType.TextCellType textCellType11 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType25 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.DateTimeCellType dateTimeCellType1 = new FarPoint.Win.Spread.CellType.DateTimeCellType(); FarPoint.Win.Spread.CellType.DateTimeCellType dateTimeCellType3 = new FarPoint.Win.Spread.CellType.DateTimeCellType();
FarPoint.Win.Spread.CellType.DateTimeCellType dateTimeCellType2 = new FarPoint.Win.Spread.CellType.DateTimeCellType(); FarPoint.Win.Spread.CellType.DateTimeCellType dateTimeCellType4 = new FarPoint.Win.Spread.CellType.DateTimeCellType();
FarPoint.Win.Spread.CellType.TextCellType textCellType12 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType26 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.TextCellType textCellType13 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType27 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.NumberCellType numberCellType4 = new FarPoint.Win.Spread.CellType.NumberCellType(); FarPoint.Win.Spread.CellType.NumberCellType numberCellType9 = new FarPoint.Win.Spread.CellType.NumberCellType();
FarPoint.Win.Spread.CellType.TextCellType textCellType14 = new FarPoint.Win.Spread.CellType.TextCellType(); FarPoint.Win.Spread.CellType.TextCellType textCellType28 = new FarPoint.Win.Spread.CellType.TextCellType();
FarPoint.Win.Spread.CellType.NumberCellType numberCellType5 = new FarPoint.Win.Spread.CellType.NumberCellType(); FarPoint.Win.Spread.CellType.NumberCellType numberCellType10 = new FarPoint.Win.Spread.CellType.NumberCellType();
this.bn = new System.Windows.Forms.BindingNavigator(this.components); this.bn = new System.Windows.Forms.BindingNavigator(this.components);
this.bs = new System.Windows.Forms.BindingSource(this.components); this.bs = new System.Windows.Forms.BindingSource(this.components);
this.dsMSSQL = new FPJ0000.dsPRJ(); this.dsMSSQL = new FPJ0000.dsPRJ();
@@ -105,7 +105,6 @@
this.tam = new FPJ0000.dsPRJTableAdapters.TableAdapterManager(); this.tam = new FPJ0000.dsPRJTableAdapters.TableAdapterManager();
this.ta = new FPJ0000.dsPRJTableAdapters.JobReportTableAdapter(); this.ta = new FPJ0000.dsPRJTableAdapters.JobReportTableAdapter();
this.fpSpread1 = new FarPoint.Win.Spread.FpSpread(); this.fpSpread1 = new FarPoint.Win.Spread.FpSpread();
this.fpSpread1_Sheet1 = new FarPoint.Win.Spread.SheetView();
this.toolStrip1 = new System.Windows.Forms.ToolStrip(); this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.toolStripButton8 = new System.Windows.Forms.ToolStripButton(); this.toolStripButton8 = new System.Windows.Forms.ToolStripButton();
this.lbStt = new System.Windows.Forms.ToolStripLabel(); this.lbStt = new System.Windows.Forms.ToolStripLabel();
@@ -128,18 +127,19 @@
this.toolStripButton6 = new System.Windows.Forms.ToolStripButton(); this.toolStripButton6 = new System.Windows.Forms.ToolStripButton();
this.richTextBox1 = new System.Windows.Forms.RichTextBox(); this.richTextBox1 = new System.Windows.Forms.RichTextBox();
this.splitContainer1 = new System.Windows.Forms.SplitContainer(); this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.fpSpread1_Sheet1 = new FarPoint.Win.Spread.SheetView();
((System.ComponentModel.ISupportInitialize)(this.bn)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.bn)).BeginInit();
this.bn.SuspendLayout(); this.bn.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.bs)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.bs)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.dsMSSQL)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.dsMSSQL)).BeginInit();
this.cm.SuspendLayout(); this.cm.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.fpSpread1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.fpSpread1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.fpSpread1_Sheet1)).BeginInit();
this.toolStrip1.SuspendLayout(); this.toolStrip1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout(); this.splitContainer1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.fpSpread1_Sheet1)).BeginInit();
this.SuspendLayout(); this.SuspendLayout();
// //
// bn // bn
@@ -228,7 +228,6 @@
// //
this.bindingNavigatorPositionItem.AccessibleName = "위치"; this.bindingNavigatorPositionItem.AccessibleName = "위치";
this.bindingNavigatorPositionItem.AutoSize = false; this.bindingNavigatorPositionItem.AutoSize = false;
this.bindingNavigatorPositionItem.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.bindingNavigatorPositionItem.Name = "bindingNavigatorPositionItem"; this.bindingNavigatorPositionItem.Name = "bindingNavigatorPositionItem";
this.bindingNavigatorPositionItem.Size = new System.Drawing.Size(50, 23); this.bindingNavigatorPositionItem.Size = new System.Drawing.Size(50, 23);
this.bindingNavigatorPositionItem.Text = "0"; this.bindingNavigatorPositionItem.Text = "0";
@@ -320,7 +319,6 @@
// tbFind // tbFind
// //
this.tbFind.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.tbFind.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.tbFind.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.tbFind.Name = "tbFind"; this.tbFind.Name = "tbFind";
this.tbFind.Size = new System.Drawing.Size(100, 25); this.tbFind.Size = new System.Drawing.Size(100, 25);
this.tbFind.KeyDown += new System.Windows.Forms.KeyEventHandler(this.tbFind_KeyDown); this.tbFind.KeyDown += new System.Windows.Forms.KeyEventHandler(this.tbFind_KeyDown);
@@ -642,193 +640,7 @@
this.fpSpread1.Size = new System.Drawing.Size(1364, 592); this.fpSpread1.Size = new System.Drawing.Size(1364, 592);
this.fpSpread1.StatusBarVisible = true; this.fpSpread1.StatusBarVisible = true;
this.fpSpread1.TabIndex = 2; this.fpSpread1.TabIndex = 2;
// this.fpSpread1.CellClick += new FarPoint.Win.Spread.CellClickEventHandler(this.fpSpread1_CellClick);
// fpSpread1_Sheet1
//
this.fpSpread1_Sheet1.Reset();
this.fpSpread1_Sheet1.SheetName = "Sheet1";
// Formulas and custom names must be loaded with R1C1 reference style
this.fpSpread1_Sheet1.ReferenceStyle = FarPoint.Win.Spread.Model.ReferenceStyle.R1C1;
this.fpSpread1_Sheet1.ColumnCount = 21;
this.fpSpread1_Sheet1.ColumnHeader.RowCount = 2;
this.fpSpread1_Sheet1.ActiveColumnIndex = -1;
this.fpSpread1_Sheet1.ActiveRowIndex = -1;
this.fpSpread1_Sheet1.AutoGenerateColumns = false;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 0).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 0).Value = "날짜";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 1).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 1).Value = "WW";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 2).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 2).Value = "담당";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 3).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 3).Value = "요청부서";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 4).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 4).Value = "패키지";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 5).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 5).Value = "상태";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 6).ColumnSpan = 3;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 6).Value = "업무형태";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 7).Value = "(공정)업무분류";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 8).Value = "업무분류";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 9).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 9).Value = "프로젝트(아이템)";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 10).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 10).Value = "*";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 11).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 11).Value = "시간";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 12).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 12).Value = "초과";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 13).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 13).Value = "비고";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 14).ColumnSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 14).Value = "초과시간범위";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 15).Value = "초과종료";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 16).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 16).Value = "기술분류";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 17).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 17).Value = "기술레벨";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 18).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 18).Value = "기술료($K)";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 19).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 19).Value = "#";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 20).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 20).Value = "일련번호";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(1, 6).Value = "형태";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(1, 7).Value = "분류";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(1, 8).Value = "공정";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(1, 14).Value = "시작";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(1, 15).Value = "종료";
this.fpSpread1_Sheet1.ColumnHeader.Rows.Get(0).Height = 30F;
this.fpSpread1_Sheet1.Columns.Get(0).CellType = textCellType1;
this.fpSpread1_Sheet1.Columns.Get(0).DataField = "pdate";
this.fpSpread1_Sheet1.Columns.Get(0).Width = 58F;
this.fpSpread1_Sheet1.Columns.Get(1).BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this.fpSpread1_Sheet1.Columns.Get(1).CellType = textCellType2;
this.fpSpread1_Sheet1.Columns.Get(1).DataField = "ww";
this.fpSpread1_Sheet1.Columns.Get(1).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(1).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(2).CellType = textCellType3;
this.fpSpread1_Sheet1.Columns.Get(2).DataField = "username";
this.fpSpread1_Sheet1.Columns.Get(2).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(2).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(3).AllowAutoFilter = true;
this.fpSpread1_Sheet1.Columns.Get(3).CellType = textCellType4;
this.fpSpread1_Sheet1.Columns.Get(3).DataField = "requestpart";
this.fpSpread1_Sheet1.Columns.Get(3).Width = 78F;
this.fpSpread1_Sheet1.Columns.Get(4).AllowAutoFilter = true;
this.fpSpread1_Sheet1.Columns.Get(4).CellType = textCellType5;
this.fpSpread1_Sheet1.Columns.Get(4).DataField = "package";
this.fpSpread1_Sheet1.Columns.Get(4).Width = 86F;
this.fpSpread1_Sheet1.Columns.Get(5).CellType = textCellType6;
this.fpSpread1_Sheet1.Columns.Get(5).DataField = "status";
this.fpSpread1_Sheet1.Columns.Get(5).Tag = "status";
this.fpSpread1_Sheet1.Columns.Get(6).AllowAutoFilter = true;
this.fpSpread1_Sheet1.Columns.Get(6).CellType = textCellType7;
this.fpSpread1_Sheet1.Columns.Get(6).DataField = "type";
this.fpSpread1_Sheet1.Columns.Get(6).Label = "형태";
this.fpSpread1_Sheet1.Columns.Get(6).Width = 84F;
this.fpSpread1_Sheet1.Columns.Get(7).AllowAutoFilter = true;
this.fpSpread1_Sheet1.Columns.Get(7).CellType = textCellType8;
this.fpSpread1_Sheet1.Columns.Get(7).DataField = "jobgrp";
this.fpSpread1_Sheet1.Columns.Get(7).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(7).Label = "분류";
this.fpSpread1_Sheet1.Columns.Get(7).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(7).Width = 90F;
this.fpSpread1_Sheet1.Columns.Get(8).AllowAutoFilter = true;
this.fpSpread1_Sheet1.Columns.Get(8).CellType = textCellType9;
this.fpSpread1_Sheet1.Columns.Get(8).DataField = "process";
this.fpSpread1_Sheet1.Columns.Get(8).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Left;
this.fpSpread1_Sheet1.Columns.Get(8).Label = "공정";
this.fpSpread1_Sheet1.Columns.Get(8).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(8).Width = 80F;
this.fpSpread1_Sheet1.Columns.Get(9).AllowAutoFilter = true;
this.fpSpread1_Sheet1.Columns.Get(9).CellType = textCellType10;
this.fpSpread1_Sheet1.Columns.Get(9).DataField = "projectName";
this.fpSpread1_Sheet1.Columns.Get(9).Width = 158F;
this.fpSpread1_Sheet1.Columns.Get(10).BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
numberCellType1.DecimalPlaces = 0;
numberCellType1.LeadingZero = FarPoint.Win.Spread.CellType.LeadingZero.Yes;
numberCellType1.MaximumValue = 2147483647D;
numberCellType1.MinimumValue = -2147483648D;
this.fpSpread1_Sheet1.Columns.Get(10).CellType = numberCellType1;
this.fpSpread1_Sheet1.Columns.Get(10).DataField = "pidx";
this.fpSpread1_Sheet1.Columns.Get(10).Tag = "pidx";
this.fpSpread1_Sheet1.Columns.Get(10).Width = 39F;
numberCellType2.MaximumValue = 999999999999999D;
numberCellType2.MinimumValue = -999999999999999D;
this.fpSpread1_Sheet1.Columns.Get(11).CellType = numberCellType2;
this.fpSpread1_Sheet1.Columns.Get(11).DataField = "hrs";
this.fpSpread1_Sheet1.Columns.Get(11).Width = 52F;
numberCellType3.MaximumValue = 999999999999999D;
numberCellType3.MinimumValue = -999999999999999D;
numberCellType3.NullDisplay = "--";
this.fpSpread1_Sheet1.Columns.Get(12).CellType = numberCellType3;
this.fpSpread1_Sheet1.Columns.Get(12).DataField = "ot";
this.fpSpread1_Sheet1.Columns.Get(12).ForeColor = System.Drawing.Color.Red;
this.fpSpread1_Sheet1.Columns.Get(12).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(12).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(13).CellType = textCellType11;
this.fpSpread1_Sheet1.Columns.Get(13).DataField = "description";
this.fpSpread1_Sheet1.Columns.Get(13).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Left;
this.fpSpread1_Sheet1.Columns.Get(13).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(13).Width = 113F;
this.fpSpread1_Sheet1.Columns.Get(14).BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(224)))), ((int)(((byte)(192)))));
dateTimeCellType1.Calendar = new System.Globalization.GregorianCalendar(System.Globalization.GregorianCalendarTypes.Localized);
dateTimeCellType1.CalendarSurroundingDaysColor = System.Drawing.SystemColors.GrayText;
dateTimeCellType1.DateTimeFormat = FarPoint.Win.Spread.CellType.DateTimeFormat.TimeOnly;
dateTimeCellType1.MaximumTime = System.TimeSpan.Parse("23:59:59.9999999");
dateTimeCellType1.TimeDefault = new System.DateTime(2025, 8, 28, 22, 53, 4, 0);
this.fpSpread1_Sheet1.Columns.Get(14).CellType = dateTimeCellType1;
this.fpSpread1_Sheet1.Columns.Get(14).DataField = "otStart";
this.fpSpread1_Sheet1.Columns.Get(14).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(14).Label = "시작";
this.fpSpread1_Sheet1.Columns.Get(14).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(15).BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(224)))), ((int)(((byte)(192)))));
dateTimeCellType2.Calendar = new System.Globalization.GregorianCalendar(System.Globalization.GregorianCalendarTypes.Localized);
dateTimeCellType2.CalendarSurroundingDaysColor = System.Drawing.SystemColors.GrayText;
dateTimeCellType2.DateTimeFormat = FarPoint.Win.Spread.CellType.DateTimeFormat.TimeOnly;
dateTimeCellType2.MaximumTime = System.TimeSpan.Parse("23:59:59.9999999");
dateTimeCellType2.TimeDefault = new System.DateTime(2025, 8, 28, 22, 53, 4, 0);
this.fpSpread1_Sheet1.Columns.Get(15).CellType = dateTimeCellType2;
this.fpSpread1_Sheet1.Columns.Get(15).DataField = "otEnd";
this.fpSpread1_Sheet1.Columns.Get(15).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(15).Label = "종료";
this.fpSpread1_Sheet1.Columns.Get(15).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(16).CellType = textCellType12;
this.fpSpread1_Sheet1.Columns.Get(16).DataField = "kisuldiv";
this.fpSpread1_Sheet1.Columns.Get(16).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(16).Tag = "kisuldiv";
this.fpSpread1_Sheet1.Columns.Get(16).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(17).CellType = textCellType13;
this.fpSpread1_Sheet1.Columns.Get(17).DataField = "kisullv";
this.fpSpread1_Sheet1.Columns.Get(17).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(17).Tag = "kisullv";
this.fpSpread1_Sheet1.Columns.Get(17).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
numberCellType4.DecimalPlaces = 2;
numberCellType4.NegativeRed = true;
this.fpSpread1_Sheet1.Columns.Get(18).CellType = numberCellType4;
this.fpSpread1_Sheet1.Columns.Get(18).DataField = "kisulamt";
this.fpSpread1_Sheet1.Columns.Get(18).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(18).Tag = "kisulamt";
this.fpSpread1_Sheet1.Columns.Get(18).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(19).CellType = textCellType14;
this.fpSpread1_Sheet1.Columns.Get(19).DataField = "tag";
this.fpSpread1_Sheet1.Columns.Get(19).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
numberCellType5.DecimalPlaces = 0;
numberCellType5.MaximumValue = 10000000D;
numberCellType5.MinimumValue = -10000000D;
this.fpSpread1_Sheet1.Columns.Get(20).CellType = numberCellType5;
this.fpSpread1_Sheet1.Columns.Get(20).DataField = "idx";
this.fpSpread1_Sheet1.Columns.Get(20).Tag = "idx";
this.fpSpread1_Sheet1.DataAutoCellTypes = false;
this.fpSpread1_Sheet1.DataAutoSizeColumns = false;
this.fpSpread1_Sheet1.DataSource = this.bs;
this.fpSpread1_Sheet1.Protect = false;
this.fpSpread1_Sheet1.RowHeader.Columns.Default.Resizable = false;
this.fpSpread1_Sheet1.SelectionPolicy = FarPoint.Win.Spread.Model.SelectionPolicy.MultiRange;
this.fpSpread1_Sheet1.ShowEditingRowSelector = true;
this.fpSpread1_Sheet1.ShowRowSelector = true;
this.fpSpread1_Sheet1.ReferenceStyle = FarPoint.Win.Spread.Model.ReferenceStyle.A1;
// //
// toolStrip1 // toolStrip1
// //
@@ -880,7 +692,6 @@
// dtSD // dtSD
// //
this.dtSD.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.dtSD.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.dtSD.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.dtSD.Name = "dtSD"; this.dtSD.Name = "dtSD";
this.dtSD.Size = new System.Drawing.Size(90, 37); this.dtSD.Size = new System.Drawing.Size(90, 37);
this.dtSD.Text = "1982-11-23"; this.dtSD.Text = "1982-11-23";
@@ -904,7 +715,6 @@
// dtED // dtED
// //
this.dtED.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.dtED.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.dtED.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.dtED.Name = "dtED"; this.dtED.Name = "dtED";
this.dtED.Size = new System.Drawing.Size(90, 37); this.dtED.Size = new System.Drawing.Size(90, 37);
this.dtED.Text = "1982-11-23"; this.dtED.Text = "1982-11-23";
@@ -940,7 +750,6 @@
// tbProcess // tbProcess
// //
this.tbProcess.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(180)))), ((int)(((byte)(180)))), ((int)(((byte)(180))))); this.tbProcess.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(180)))), ((int)(((byte)(180)))), ((int)(((byte)(180)))));
this.tbProcess.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.tbProcess.Name = "tbProcess"; this.tbProcess.Name = "tbProcess";
this.tbProcess.Size = new System.Drawing.Size(200, 37); this.tbProcess.Size = new System.Drawing.Size(200, 37);
// //
@@ -1043,6 +852,194 @@
this.splitContainer1.SplitterWidth = 10; this.splitContainer1.SplitterWidth = 10;
this.splitContainer1.TabIndex = 6; this.splitContainer1.TabIndex = 6;
// //
// fpSpread1_Sheet1
//
this.fpSpread1_Sheet1.Reset();
this.fpSpread1_Sheet1.SheetName = "Sheet1";
// Formulas and custom names must be loaded with R1C1 reference style
this.fpSpread1_Sheet1.ReferenceStyle = FarPoint.Win.Spread.Model.ReferenceStyle.R1C1;
this.fpSpread1_Sheet1.ColumnCount = 21;
this.fpSpread1_Sheet1.ColumnHeader.RowCount = 2;
this.fpSpread1_Sheet1.ActiveColumnIndex = -1;
this.fpSpread1_Sheet1.ActiveRowIndex = -1;
this.fpSpread1_Sheet1.AutoGenerateColumns = false;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 0).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 0).Value = "날짜";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 1).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 1).Value = "WW";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 2).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 2).Value = "담당";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 3).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 3).Value = "요청부서";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 4).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 4).Value = "패키지";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 5).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 5).Value = "상태";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 6).ColumnSpan = 3;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 6).Value = "업무형태";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 7).Value = "(공정)업무분류";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 8).Value = "업무분류";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 9).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 9).Value = "프로젝트(아이템)";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 10).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 10).Value = "*";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 11).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 11).Value = "시간";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 12).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 12).Value = "초과";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 13).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 13).Value = "비고";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 14).ColumnSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 14).Value = "초과시간범위";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 15).Value = "초과종료";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 16).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 16).Value = "기술분류";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 17).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 17).Value = "기술레벨";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 18).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 18).Value = "기술료($K)";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 19).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 19).Value = "#";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 20).RowSpan = 2;
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(0, 20).Value = "일련번호";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(1, 6).Value = "형태";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(1, 7).Value = "분류";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(1, 8).Value = "공정";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(1, 14).Value = "시작";
this.fpSpread1_Sheet1.ColumnHeader.Cells.Get(1, 15).Value = "종료";
this.fpSpread1_Sheet1.ColumnHeader.Rows.Get(0).Height = 30F;
this.fpSpread1_Sheet1.Columns.Get(0).CellType = textCellType15;
this.fpSpread1_Sheet1.Columns.Get(0).DataField = "pdate";
this.fpSpread1_Sheet1.Columns.Get(0).Width = 58F;
this.fpSpread1_Sheet1.Columns.Get(1).BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
this.fpSpread1_Sheet1.Columns.Get(1).CellType = textCellType16;
this.fpSpread1_Sheet1.Columns.Get(1).DataField = "ww";
this.fpSpread1_Sheet1.Columns.Get(1).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(1).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(2).CellType = textCellType17;
this.fpSpread1_Sheet1.Columns.Get(2).DataField = "username";
this.fpSpread1_Sheet1.Columns.Get(2).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(2).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(3).AllowAutoFilter = true;
this.fpSpread1_Sheet1.Columns.Get(3).CellType = textCellType18;
this.fpSpread1_Sheet1.Columns.Get(3).DataField = "requestpart";
this.fpSpread1_Sheet1.Columns.Get(3).Width = 78F;
this.fpSpread1_Sheet1.Columns.Get(4).AllowAutoFilter = true;
this.fpSpread1_Sheet1.Columns.Get(4).CellType = textCellType19;
this.fpSpread1_Sheet1.Columns.Get(4).DataField = "package";
this.fpSpread1_Sheet1.Columns.Get(4).Width = 86F;
this.fpSpread1_Sheet1.Columns.Get(5).CellType = textCellType20;
this.fpSpread1_Sheet1.Columns.Get(5).DataField = "status";
this.fpSpread1_Sheet1.Columns.Get(5).Tag = "status";
this.fpSpread1_Sheet1.Columns.Get(6).AllowAutoFilter = true;
this.fpSpread1_Sheet1.Columns.Get(6).CellType = textCellType21;
this.fpSpread1_Sheet1.Columns.Get(6).DataField = "type";
this.fpSpread1_Sheet1.Columns.Get(6).Label = "형태";
this.fpSpread1_Sheet1.Columns.Get(6).Width = 84F;
this.fpSpread1_Sheet1.Columns.Get(7).AllowAutoFilter = true;
this.fpSpread1_Sheet1.Columns.Get(7).CellType = textCellType22;
this.fpSpread1_Sheet1.Columns.Get(7).DataField = "jobgrp";
this.fpSpread1_Sheet1.Columns.Get(7).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(7).Label = "분류";
this.fpSpread1_Sheet1.Columns.Get(7).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(7).Width = 90F;
this.fpSpread1_Sheet1.Columns.Get(8).AllowAutoFilter = true;
this.fpSpread1_Sheet1.Columns.Get(8).CellType = textCellType23;
this.fpSpread1_Sheet1.Columns.Get(8).DataField = "process";
this.fpSpread1_Sheet1.Columns.Get(8).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Left;
this.fpSpread1_Sheet1.Columns.Get(8).Label = "공정";
this.fpSpread1_Sheet1.Columns.Get(8).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(8).Width = 80F;
this.fpSpread1_Sheet1.Columns.Get(9).AllowAutoFilter = true;
this.fpSpread1_Sheet1.Columns.Get(9).CellType = textCellType24;
this.fpSpread1_Sheet1.Columns.Get(9).DataField = "projectName";
this.fpSpread1_Sheet1.Columns.Get(9).Width = 158F;
this.fpSpread1_Sheet1.Columns.Get(10).BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
numberCellType6.DecimalPlaces = 0;
numberCellType6.LeadingZero = FarPoint.Win.Spread.CellType.LeadingZero.Yes;
numberCellType6.MaximumValue = 2147483647D;
numberCellType6.MinimumValue = -2147483648D;
this.fpSpread1_Sheet1.Columns.Get(10).CellType = numberCellType6;
this.fpSpread1_Sheet1.Columns.Get(10).DataField = "pidx";
this.fpSpread1_Sheet1.Columns.Get(10).Tag = "pidx";
this.fpSpread1_Sheet1.Columns.Get(10).Width = 39F;
numberCellType7.MaximumValue = 999999999999999D;
numberCellType7.MinimumValue = -999999999999999D;
this.fpSpread1_Sheet1.Columns.Get(11).CellType = numberCellType7;
this.fpSpread1_Sheet1.Columns.Get(11).DataField = "hrs";
this.fpSpread1_Sheet1.Columns.Get(11).Width = 52F;
numberCellType8.MaximumValue = 999999999999999D;
numberCellType8.MinimumValue = -999999999999999D;
numberCellType8.NullDisplay = "--";
this.fpSpread1_Sheet1.Columns.Get(12).CellType = numberCellType8;
this.fpSpread1_Sheet1.Columns.Get(12).DataField = "ot";
this.fpSpread1_Sheet1.Columns.Get(12).ForeColor = System.Drawing.Color.Red;
this.fpSpread1_Sheet1.Columns.Get(12).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(12).Tag = "ot";
this.fpSpread1_Sheet1.Columns.Get(12).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(13).CellType = textCellType25;
this.fpSpread1_Sheet1.Columns.Get(13).DataField = "description";
this.fpSpread1_Sheet1.Columns.Get(13).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Left;
this.fpSpread1_Sheet1.Columns.Get(13).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(13).Width = 113F;
this.fpSpread1_Sheet1.Columns.Get(14).BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(224)))), ((int)(((byte)(192)))));
dateTimeCellType3.Calendar = new System.Globalization.GregorianCalendar(System.Globalization.GregorianCalendarTypes.Localized);
dateTimeCellType3.CalendarSurroundingDaysColor = System.Drawing.SystemColors.GrayText;
dateTimeCellType3.DateTimeFormat = FarPoint.Win.Spread.CellType.DateTimeFormat.TimeOnly;
dateTimeCellType3.MaximumTime = System.TimeSpan.Parse("23:59:59.9999999");
dateTimeCellType3.TimeDefault = new System.DateTime(2025, 11, 11, 22, 53, 4, 0);
this.fpSpread1_Sheet1.Columns.Get(14).CellType = dateTimeCellType3;
this.fpSpread1_Sheet1.Columns.Get(14).DataField = "otStart";
this.fpSpread1_Sheet1.Columns.Get(14).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(14).Label = "시작";
this.fpSpread1_Sheet1.Columns.Get(14).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(15).BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(224)))), ((int)(((byte)(192)))));
dateTimeCellType4.Calendar = new System.Globalization.GregorianCalendar(System.Globalization.GregorianCalendarTypes.Localized);
dateTimeCellType4.CalendarSurroundingDaysColor = System.Drawing.SystemColors.GrayText;
dateTimeCellType4.DateTimeFormat = FarPoint.Win.Spread.CellType.DateTimeFormat.TimeOnly;
dateTimeCellType4.MaximumTime = System.TimeSpan.Parse("23:59:59.9999999");
dateTimeCellType4.TimeDefault = new System.DateTime(2025, 11, 11, 22, 53, 4, 0);
this.fpSpread1_Sheet1.Columns.Get(15).CellType = dateTimeCellType4;
this.fpSpread1_Sheet1.Columns.Get(15).DataField = "otEnd";
this.fpSpread1_Sheet1.Columns.Get(15).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(15).Label = "종료";
this.fpSpread1_Sheet1.Columns.Get(15).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(16).CellType = textCellType26;
this.fpSpread1_Sheet1.Columns.Get(16).DataField = "kisuldiv";
this.fpSpread1_Sheet1.Columns.Get(16).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(16).Tag = "kisuldiv";
this.fpSpread1_Sheet1.Columns.Get(16).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(17).CellType = textCellType27;
this.fpSpread1_Sheet1.Columns.Get(17).DataField = "kisullv";
this.fpSpread1_Sheet1.Columns.Get(17).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(17).Tag = "kisullv";
this.fpSpread1_Sheet1.Columns.Get(17).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
numberCellType9.DecimalPlaces = 2;
numberCellType9.NegativeRed = true;
this.fpSpread1_Sheet1.Columns.Get(18).CellType = numberCellType9;
this.fpSpread1_Sheet1.Columns.Get(18).DataField = "kisulamt";
this.fpSpread1_Sheet1.Columns.Get(18).HorizontalAlignment = FarPoint.Win.Spread.CellHorizontalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(18).Tag = "kisulamt";
this.fpSpread1_Sheet1.Columns.Get(18).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
this.fpSpread1_Sheet1.Columns.Get(19).CellType = textCellType28;
this.fpSpread1_Sheet1.Columns.Get(19).DataField = "tag";
this.fpSpread1_Sheet1.Columns.Get(19).VerticalAlignment = FarPoint.Win.Spread.CellVerticalAlignment.Center;
numberCellType10.DecimalPlaces = 0;
numberCellType10.MaximumValue = 10000000D;
numberCellType10.MinimumValue = -10000000D;
this.fpSpread1_Sheet1.Columns.Get(20).CellType = numberCellType10;
this.fpSpread1_Sheet1.Columns.Get(20).DataField = "idx";
this.fpSpread1_Sheet1.Columns.Get(20).Tag = "idx";
this.fpSpread1_Sheet1.DataAutoCellTypes = false;
this.fpSpread1_Sheet1.DataAutoSizeColumns = false;
this.fpSpread1_Sheet1.DataSource = this.bs;
this.fpSpread1_Sheet1.Protect = false;
this.fpSpread1_Sheet1.RowHeader.Columns.Default.Resizable = false;
this.fpSpread1_Sheet1.SelectionPolicy = FarPoint.Win.Spread.Model.SelectionPolicy.MultiRange;
this.fpSpread1_Sheet1.ShowEditingRowSelector = true;
this.fpSpread1_Sheet1.ShowRowSelector = true;
this.fpSpread1_Sheet1.ReferenceStyle = FarPoint.Win.Spread.Model.ReferenceStyle.A1;
//
// fJobReport // fJobReport
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
@@ -1062,13 +1059,13 @@
((System.ComponentModel.ISupportInitialize)(this.dsMSSQL)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.dsMSSQL)).EndInit();
this.cm.ResumeLayout(false); this.cm.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.fpSpread1)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.fpSpread1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.fpSpread1_Sheet1)).EndInit();
this.toolStrip1.ResumeLayout(false); this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout(); this.toolStrip1.PerformLayout();
this.splitContainer1.Panel1.ResumeLayout(false); this.splitContainer1.Panel1.ResumeLayout(false);
this.splitContainer1.Panel2.ResumeLayout(false); this.splitContainer1.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
this.splitContainer1.ResumeLayout(false); this.splitContainer1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.fpSpread1_Sheet1)).EndInit();
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();

View File

@@ -13,6 +13,7 @@ namespace FPJ0000
{ {
public partial class fJobReport : FCOMMON.fBase public partial class fJobReport : FCOMMON.fBase
{ {
int curLevel = 0;// Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
string fn_fpcolsize = ""; string fn_fpcolsize = "";
public fJobReport() public fJobReport()
{ {
@@ -23,7 +24,7 @@ namespace FPJ0000
dtSD.KeyDown += dtSD_KeyDown; dtSD.KeyDown += dtSD_KeyDown;
dtED.KeyDown += dtSD_KeyDown; dtED.KeyDown += dtSD_KeyDown;
curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
} }
void __Closed(object sender, FormClosedEventArgs e) void __Closed(object sender, FormClosedEventArgs e)
@@ -144,7 +145,7 @@ namespace FPJ0000
//일반사용자의경우에는 상태를 변경하지 못한다. //일반사용자의경우에는 상태를 변경하지 못한다.
int curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
if (curLevel >= 5) if (curLevel >= 5)
{ {
btSave.Visible = true; btSave.Visible = true;
@@ -263,9 +264,16 @@ namespace FPJ0000
return; return;
} }
string request = cmbUser.Text.Substring(cmbUser.Text.LastIndexOf('(') + 1); string request = cmbUser.Text.Substring(cmbUser.Text.LastIndexOf('(') + 1);
request = request.Substring(0, request.Length - 1); request = request.Substring(0, request.Length - 1);
if (cmbUser.SelectedIndex == 0) request = "%"; //전체검색 201028 - chi(임현대) if (cmbUser.SelectedIndex == 0) request = "%";
//사용자 목록다중선택으로 인해 처리 //사용자 목록다중선택으로 인해 처리
@@ -314,6 +322,21 @@ namespace FPJ0000
//else //else
// this.ta.FillByTagOnly(this.dsMSSQL.JobReport, dtSD.Text, dtED.Text, request, FCOMMON.info.Login.gcode); // this.ta.FillByTagOnly(this.dsMSSQL.JobReport, dtSD.Text, dtED.Text, request, FCOMMON.info.Login.gcode);
int curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
if ( request != FCOMMON.info.Login.no && curLevel < 5)
{
this.fpSpread1_Sheet1.Columns["ot"].Visible = false;
}
else
{
this.fpSpread1_Sheet1.Columns["ot"].Visible = true;
}
RefreshTime(); RefreshTime();
FPUtil.ColSizeLoad(ref this.fpSpread1, fn_fpcolsize); FPUtil.ColSizeLoad(ref this.fpSpread1, fn_fpcolsize);
FormattingData(); FormattingData();
@@ -824,6 +847,11 @@ namespace FPJ0000
private void toolStripButton11_Click(object sender, EventArgs e) private void toolStripButton11_Click(object sender, EventArgs e)
{ {
if(curLevel < 5)
{
AR.UTIL.MsgE("사용 권한이 없습니다");// util.MsgE("");
return;
}
var f = new JobReport_.rJobReportUser(); var f = new JobReport_.rJobReportUser();
f.Show(); f.Show();
} }
@@ -983,5 +1011,10 @@ namespace FPJ0000
} }
} }
private void fpSpread1_CellClick(object sender, FarPoint.Win.Spread.CellClickEventArgs e)
{
}
} }
} }

View File

@@ -130,225 +130,227 @@
<data name="bindingNavigatorMoveFirstItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="bindingNavigatorMoveFirstItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vQAADr0BR/uQrQAAASpJREFUOE9jGDygcNbz/00Lnv/PnPj4P1QIA4S3P8Apx5A789n/VUfe/8elKL77 vQAADr0BR/uQrQAAATFJREFUOE9jYBg0oHDW8/9NC57/z5z4+D+6HAyEtz/AKceQO/PZ/1VH3v/HpSi+
wf/ghmu4DciY8vT/wn0fsCqK73n4f+n+///9qy/gNiCh58n/aVveYyiKaL8P1pw56/9/r9ITuA2I7Hr0 +8H/4IZrWOXAIGPK0/8L933Aqii+5+H/pfv///evvoAhBwcJPU/+T9vyHkNRRPt9sObMWf//e5WewG1A
v3f1BxRFoa33wJpb1wFt7/z73yX/AG4DApsf/q+b/w6uKLjl7v9Fe///7wBqzpjz879d3c//9hnbcRvg ZNej/72rP6AoCm29B9bcuu7/f//Ov/9d8g/gNiCw+eH/uvnv4IqCW+7+X7T3//+Odf//Z8z5+d+u7ud/
UXX/f/60NyiK7Ipv/0+f8/u/f9e3/zqF7/5bJKzHbYB96d3/2ZNfYyjSTzn/36ToxX+VrE//jSOX4TbA +4ztuA3wqLr/P3/aGxRFdsW3/6fP+f3fv+vbf53Cd/8tEtbjNsC+9O7/7MmvMRTpp5z/b1L04r9K1qf/
Iu/O/9T+11gVGSSd+C+b9vW/bvA83AYYZt3+H9byEqci/dTL/zV8p+E2QCftxn+/6od4Fal4TMBtgFPu xpHLcBtgkXfnf2r/a6yKDJJO/JdN+/pfN3gehhwcGGbd/h/W8hKnIv3Uy/81fKdhlQMDnbQb//2qH+JV
lf8gBXgVDULAwAAA8HbAq6XlmnAAAAAASUVORK5CYII= pOIxAaccg1Pulf8gBXgVDUoAAPB2wKtYlLYeAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="bindingNavigatorMovePreviousItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="bindingNavigatorMovePreviousItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vQAADr0BR/uQrQAAALZJREFUOE9jGDogvP3BfyiTdBDf/eB/cMM18gyI73n4f+n+///9qy+QbkBE+32w vQAADr0BR/uQrQAAALtJREFUOE9jYBgyILz9wX90MaJBfPeD/8EN18gzIL7n4f+l+///96++QLoBEe33
5sxZ//97lZ4gzYDQ1ntgza3rgLZ3/v3vkn+AeAOCW+7+X7T3//8OoOaMOT//29X9/G+fsZ00F9gV3/6f wZozZ/3/71V6gjQDQlvvgTW3rvv/37/z73+X/APEGxDccvf/or3//3es+/8/Y87P/3Z1P//bZ2wn3gAQ
Puf3f/+ub/91Ct/9t0hYT3oY6Kec/29S9OK/Stan/8aRy0g3AAQMkk78l037+l83eB55BoCAfurl/xq+ sCu+/T99zu///l3f/usUvvtvkbCeNANAQD/l/H+Tohf/VbI+/TeOXEa6ASBgkHTiv2za1/+6wfPIMwAE
08g3AARUPCZQZsBgBQwMANAUYJgEulBVAAAAAElFTkSuQmCC 9FMv/9fwnUa+ASCg4jGBMgMGLwAA0BRgmCws/7cAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="bindingNavigatorMoveNextItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="bindingNavigatorMoveNextItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vQAADr0BR/uQrQAAAKNJREFUOE9jGHygcNbz/1AmeSB35rP/Cd33yDckY8rT//P2//6f0HWHPEMSep78 vQAADr0BR/uQrQAAAKRJREFUOE9jYBh0oHDW8//oYiSB3JnP/id03yPfkIwpT//P2//7f0LXHfIMSeh5
n73v1//OrX//u5VeJt2QyK5H/6ds+/W/ZOnf/wnT//63yT1LmiGBzQ//t659D9ZsXPLlv3T0tf/GkcuI 8n/2vl//O7f+/e9Wepl0QyK7Hv2fsu3X/5Klf/8nTP/73yb3LGmGBDY//N+69j1Ys3HJl//S0df+G0cu
N8Sj6v7/krnv4JoVXXpIc4F96d3/gS3PyNMMAhZ5d/7bFFwhTzMIGGbdJl8zCOik3SBf81AEDAwAoH5f I94Qj6r7/0vmvoNrVnTpIV4zCNiX3v0f2PKMPM0gYJF3579NwRXyNIOAYdZt8jWDgE7aDfI1D00AAKB+
oAc0QjgAAAAASUVORK5CYII= X6Bjq5qXAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="bindingNavigatorMoveLastItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="bindingNavigatorMoveLastItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vQAADr0BR/uQrQAAASxJREFUOE9jGFygcNbz/1AmBgDJNS14/j9z4mOcahhyZz77n9B9D6sCkNyqI+// vQAADr0BR/uQrQAAAStJREFUOE9jYBhUoHDW8//oYjAAkmta8Px/5sTHONUw5M589j+h+x5WBSC5VUfe
h7c/wG1AxpSn/+ft//0/oesOhiKQ3MJ9H/4HN1zDbUBCz5P/s/f9+t+59e9/t9LLKApBctO2vP/vX30B /w9vf4BVHgwypjz9P2//7/8JXXcwFIHkFu778D+44RqGHBwk9Dz5P3vfr/+dW//+dyu9jKIQJDdty/v/
twGRXY/+T9n263/J0r//E6b//W+TexauGCTXu/rDf6/SE7gNCGx++L917XuwZuOSL/+lo6/9N45cBtYA /tUXcBsQ2fXo/5Rtv/6XLP37P2H63/82uWfhikFyvas//PcqPYHbgMDmh/9b174HazYu+fJfOvraf+PI
kqub/+6/S/4B3AZ4VN3/XzL3HVyzoksPXDFILn/am//2GdtxG2Bfevd/YMszDM0gAJLLnvz6v0XCetwG ZWANILm6+e/+u+QfwG2AR9X9/yVz38E1K7r0wBWD5PKnvflvn7EdtwH2pXf/B7Y8w9AMk8ue/Pq/RcJ6
WOTd+W9TcAVDMwiA5FL7X8O9hBUYZt3GqhkEQHJhLS//6wbPw22ATtoNnJIgOb/qh/81fKfhNgAfcMq9 3AZY5N35b1NwBUMzTC61/zXcS1iBYdZtrJpBACQX1vLyv27wPKzyYKCTdgOnJEjOr/rhfw3faTjV4AVO
8l/FYwIYQ4UGBWBgAAC+0b+zuQxOnAAAAABJRU5ErkJggg== uVf+q3hMAGN0uYEFAL7Rv7NmXVYYAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="btAdd.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="btAdd.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vQAADr0BR/uQrQAAAUpJREFUOE9jGLzg7gL2/7fmcf6/Oofr/8UZvP+hwsSD60CNfx41/v/zsOH/yckC vQAADr0BR/uQrQAAAVdJREFUOE/Nz0tLAmEUBmB3kWRoCUVEISFUJGb1OywiKrDsIpZdkJAkDUvDQkij
pBtwfjov3ICDPSKkG3B8kiBQc93/Pw+q/u9oFydswKWZPP/PTuX7fxKo8Ui/0P993SJAzeX//94r+r++ UKSbVIvatKhNi9oERRAGEQXhjJdp7Hd83/eGs2jhLGQ20QtndTgP71Gp/m0KZ1XInlTjM6XG+4EG5fuK
Qeb/qhq5/0srFf/PL1X+P6tIFdPAU0B//nlYD9RUC8SV///cKwHivP9/72b+/3sn+f/f23H//92MAOKQ yaTUIN8bIMUQ0gmtcuBtX/MLPMT0yoHnuA6kuA4iruI20lAZ+DiswWuyFum4Dk+7dbiP6kHEFVDBg+tQ
/5NyNDENONQrDHbu3/ulQI0FQI3ZQI2pQI0J///digZqDPv/70bQ/3/X/f53peliGrCzXeL/lmap/+vA My4DLbjwG3DqbcORxygHXxJakGIQRFwDEf0gwjKI4AYtzIHmHaA5Oxg/CsYPIb7YIQced+qluvTLCyIs
zpX/v6RC8f/fWzFAjeH/p+Zp/J+QpfW/O0P3f3uq/v/mREPCYTIb6E+Qc//dCPjfk6FDWAM6APnz3w1/ gRYWQPNO0NwkWNYGxg+DcYNgGSu2Z0xy4C7SiJtwE66kuq049xlAs2Ng/AiS7nbszXci6jIh4jQjPGWR
IPb735qsT7oB3em6YP+CcH2cEekGtCQZ/G+IN/xfE2v8vzLahHQD6AQYGAAkI9iedfyIaQAAAABJRU5E A+U59hiluowbQMzVVfmgPKU/GdcPxlmx5TArB6KzJunf0gTtPcqBzeluhCYsCIz3wm/rUw78WX4AJCPY
rkJggg== nlwVm9EAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="btEdit.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="btEdit.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEvSURBVDhPpZI/S0JRGIed+i6Nbk0t0iCuSkuDi1MfIKfm YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEuSURBVDhPpZKxS0JBHMff1P/S2NbUIg7RqrQ0tDj5B9jU
+gAOQktTQkMggYtRkwgidKmgyQwMCgqz0CivvvK8cK7neG4KdeHhHs45v+c9/xLyz08Ft713OQ+6SqXV nH+Ag9DSlOAQhNCi6BRBBD1SaDIDg4JCLVSqpz/5HJzdz3vp4MH3vcfdfT73e3cXyJot4NHs9qUSdkxK
kfLlnXJw1lSK5VrERqGkMB4JCCLpvQ7lZfDlQJ+B4EnwI9nTkbYdAZMbjxOPq4eJPH1MvXC2sD8XsOzP t20p1lsmJxc3JkfFq3m2MwUTxucCQCTd96G8DcYq9NkAnoc/kiqPzLcSMPn6eeKl8TSRl8+pB6cyx38C
0bcX/C3MXEfAfmzBsnCnP10uWBWu3IS+gJOm0w5fHCZiw0aQzu3GC0xYgm2R+poTRnh8HeqNOALu920w yv4afXvgfzBzlYD/cQXL4HZvulywCi49RL6AnabThWv5IBa2gt10Nl5gYQn3RaobCkZ4dh+ZE1ECzvdj
9MK0F8NGkMrs+ALewqrwUXss3ed+vKB6H+rh2OT3SjpO0IBgcyvnCjgDBGCq8mcMiQ3FHAGdLB/J4vMF MPRgvhdhK0jsHfgC7sIq+PTuVzqvvXjB5WNkNsfNYa5gxgFtEOwk01rAHiAgdlXejCFxw2JKQCflI1m8
KhoI83LXk6m5gCpmufbyOWlgv0BVIMx4JPj7JzIDGHRUPz2nxiQAAAAASUVORK5CYII= voQVbYC5uZtbCV2BLdctn50m/C9hVQKs7sE6bQYYdFQ/+SVRqQAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="btDel.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="btDel.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
vQAADr0BR/uQrQAAAW9JREFUOE+1kE0ow2Ecx3dV3krt4oJaOSCTvIRkMqSxyITIzCQHDouEdnFwIOVC vQAADr0BR/uQrQAAAWtJREFUOE+1kE0ow2Ecx/9X5a2UiwtKOSCTmJBMhuQlMo3IvCUHDouEXHZwIOVC
DrhIDiQl5UTiNG/z2ppafy1S2gX/uDwfY6i1v7Hie3nqeb7fz+/7/FR/Ilwn0G0Exw4fV5GJlXlEZxXC DrhIDiQl5USy07zNa2tKf2laaRf84/J8xBCetab4XL/f76fn+SnKX4DrGLqrwbHDzywkWJlHdJYjLEbY
rIet9bAQvB5Ymgn2sLYAvSZEux7RUQFzE4qQt4bCXAYjPaHvnDoCkLpsRGMB2JqCTGLIijDlwqQ9bEMV Wg8q4eYKlma+d1hbgF4TotWIaC+FuYmAktcXCksx2HrknBOHX1KbiTDngrXhW0kMdSBM2TA5Io+/wuI0
i9OIytR3EMNWcJ/BWH8A6j8/bOGFxwXNxYEvGbMQ9XnQ1/K78KfY3/VXzkMY0qFGG2H4RoLGQshJQNbG oiz5TcRwB7hPYazfLx3rDz7+gCsXNBb4v1SdgajTQ19TaOMP2NtFmPSIilSo0v1y7FHBnAdZMWi6aO51
86CNhdrsX9a/uQZTPhQl4rMY4OLofbl3aX7I8uwPC7y/g1YdjyVJuEvT8e1tfwUYteHUxCCfHChDeHmG kVCTGZoEzzWYciA/Dl9bBZwfvh3XmxIJy7PBJdx5odnAQ2E87qJUfPbtzwGjVpxJEWjH+4ElPD/BYBsY
QQvokjlOU+PbWA0x3pZnILVVI3uvQyHsbiLnqnGmRCF1NYD8pDhpRxOH7HQoAKZGkFKjceszQbpSrumX EjhKicW3sSoVb0vSUFsq0W6upUxhdxMtOxZnYhhqVz1oj3JJUZSdpCg0p0POmLKhJofjNqaDeikX3tFG
bO+G80MFwKUTxgfgcO/b8D9IpXoFiiMDHIQm0skAAAAASUVORK5CYII= uuHsQM65cML4ABzY5fA/eQGKIwMcVjm2bAAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="btFind.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="btFind.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE3SURBVDhPnZIxS8NQFEb7W/wLjh0Fl9a1SxBHBekkWFd1 YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEwSURBVDhPpZIxSwNBEIXzW/wLKS0Fm2ib5hBLBbESjG20
qYg4Ci5dndSCg2AHl4LQSaRSKDqoFUE7VAjUmvTKueWmL2mw2gunL7zmO+/mJhmZoTJusdF868vpXUfO UUQsBRtbKzVgIWhhIwhWIhFBtFAjgqaIcKDmLiPfwO7NXg6NZuDdLnv3vn03uyX5R5VssdB8+ZC9q5Yc
b5/lpPEox9f3SvnsRtk8uojxHQ7HEgSEkXS6vrz3xqtdu+xdfUiheEBsJOGCk/mz/hROUHsIIrp+qIKY XD7K7sW9bJ9eq1b3z1WLW4eBumkvgwDADKTVjuW1k41ubrV2/CbV+Y0sCRN25uXZQ9qnk7vEqx2nCggg
hB/a9r+CVAG4Auj5g7iA5/1NACaptgIVLHkb0wWVw13ZL60p2+uerqkCJs1mMgwUU6d1k/xJwI10RZj1 PIgdfyZ95jwEAOrEXyGA//0JYCGNm0QBk9HC74CdzRVZr82q6nORjoUAOs1i3owouk50BxkIwIekwsz4
9TPUN7Wam9dgTMC75QR7TjCBkRQs5Jd1jQS8c1ewtZLTPcQW/peADpC44cudgnjZOQ1OCGjTwkwaGBon /J7qSc1UymoMAJwtO9iOO4BTHjA2MRUCOHMLWJqu6BpgZ/4TgARArPlouSrR6EgxgJj2qBBNY0cnzI3a
GoSrpcVIQqmAj6LZftFBup9vWiUlUQdIDCbsQrsGZRJKBbOXyA++SlEsu6QjvQAAAABJRU5ErkJggg== uId4AJeiefukjbTXt6jyEJ8AiBMdtiKuk4V4wDD1Db5KUSxr13uqAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="btImport.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="btImport.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE8SURBVDhPnZI/S0JRGIf9Oo19ARdziDZBGmwRx5amFsG5 YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE5SURBVDhPpZK9S0JRGIf9dxr7B1rMQdwCadBFGl2aXILm
BolahJbWmkKwKYQ2BZGISohABIWCjJDsgmj3xHPivfc99yCCB56r98/vOed9z0mZNUZKDx48vU1N42Fg GiRqEVxcc4rApgjcCiQi+gAJRFBQUBGpLkh2Tzwn3ut570mCOvBcvR+/55z3PSdh/jAS7uDB4+DNNO67
uez0zfldz3J03bYc1hoOjoQbgkhG4x/zMQkceKY5vh2b3YPTWCICPm4NQ49m/zfiMwitwJFwYdnfwcwL ltNWx1Sbz5aDsxtLqdJQKAk3BJH0x+9mNAsUPHM5vByb7d3jpUQEfHzdCz2uOp8RkyC0AiXhwrJfg7kX
l06yngD4NlcsxwLqTQoIa8HNyyJipYDgWbcQSQT6dPU49wV0WgTF6pap1AtWoEEwnISRYDu/7wtYalLA 3jlKeQLg263C3lJAvXEBYVdw0V5E/CogeHKbiyQCfao/fPgCOi2CQnnT7J/nrMAFQW8WRoJ0tugLWGpc
f9ACdsMRsLfsgtSLhDC/ugQEF/f/gszO3nIBjZIwIaA8wjB4/1oukE6zVAQ6WOssLAjS2bwrkB5ogZAU wH9wBeyGErC37ILUi4Qwv24JCGp334JkJr9aQKMkTAgojzB0h9PVAuk0S0XgBiuthQXBRiqrBdIDVyDE
MJkj4FQ9v46shJf66AIzCrzn5G5sZmIBK0AisMdAp4F6BWYm7JyD9Ycxf8jQQxybOGd5AAAAAElFTkSu BUymBJyqp5e+lfx0fJlR4D0nd209qVeARGCPgU4D9QrMTFidg/+ML8jQQxyg3treAAAAAElFTkSuQmCC
QmCC
</value> </value>
</data> </data>
<data name="btOpenFolder.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="btOpenFolder.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw /aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D 1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC
TgDQASA1MVpwzwAAAABJRU5ErkJggg== nOccAdABIDXXE1nzAAAAAElFTkSuQmCC
</value>
</data>
<data name="toolStripButton10.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAALwSURBVDhPhZJZTxNRGIZ7JT/BoBdekhiFKEaNXigIWMAE
NwSCyFYKAQEJ1GAi1hSMyGJAAiRqCETjhRpwgQKWrZTSNhQDMpZF9i1hqUCXGehMeT0zrYAJiV/y5Fyc
eZ/M986I+Al8qI67UqxXhZXofwfJ9TQ5GYFS/jQwYcU6JuSZljov05QfDX9/QAjtneAnPZplC7NKURRn
tm3CbN1l1cLDYHjRgrwvs4gqGbGL05Ue7qhrQgu1yxRl4nTTDhhmWBhmWeinWWintqD+tYkWkw2bLNA4
QiPv0wwSX1D0P5IgeQu9Yd9C/xyH73MsOVn0CZItdI9v4pvJTgRO9C9yMCw4UKCchf+DjndCOLLUb/KW
PHxbWnUDiZU3Udlah/z6UvjLveFHEBecQ6DiNMoay4RVrAyLpTU7AmO7WUEQUez/sWOoCU1jr1GpzxEk
sRUhyHkbg4y6KEiqryKhOgGNg0tooqz4+mMD66SnIEUPIwjE5WIPH3kmpx/twpshBYrU6YIkriqUhK8h
5WUyNOM2YZX2MRoq0sOazYGg/F6XgJ/gwm4mqyYexnEtqg338bQtG5GllxBXEQ7jtB1GUixfsGbC1YmZ
CAIVewQXHskdZ3KPIKZcjP4JHQq6UqFQZiHqeQDq1J8xMM/CSIrVTTnQS1i2OOD/2C04KfOU+soOI6M2
GrerghFddlmQZCljIKtPJm8SAP6+f5ZDH/+JCRZSpE+m1iXwlR2c95UdIg95wjfHE9eLApD2Kh4akwoF
qlykfoiHpCoCRiIwkH9DTwSMw0kE6t0VLmb2MIvrDAbnOYHu0QXcq0lBEglKq6OQXXt3547HvsURQcOu
gLfNmXcF/8PGr5C8R3A2q9Ou0g1u7/fwflDDo87jsY1Wd5wUmdI2ObNht3Tqh5yTKzQml2mMu1mxOgT4
5q0MhwFqxEnT9LrXneaf7rhIdCqlNc1H0tJ2Qqoy+0gbmB2SXHj/RdLAeEma144lNLd7xysTRSKR6A+3
VJ80gqHE3AAAAABJRU5ErkJggg==
</value>
</data>
<data name="toolStripButton11.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE3SURBVDhPnZIxS8NQFEb7W/wLjh0Fl9a1SxBHBekkWFd1
qYg4Ci5dndSCg2AHl4LQSaRSKDqoFUE7VAjUmvTKueWmL2mw2gunL7zmO+/mJhmZoTJusdF868vpXUfO
b5/lpPEox9f3SvnsRtk8uojxHQ7HEgSEkXS6vrz3xqtdu+xdfUiheEBsJOGCk/mz/hROUHsIIrp+qIKY
hB/a9r+CVAG4Auj5g7iA5/1NACaptgIVLHkb0wWVw13ZL60p2+uerqkCJs1mMgwUU6d1k/xJwI10RZj1
9TPUN7Wam9dgTMC75QR7TjCBkRQs5Jd1jQS8c1ewtZLTPcQW/peADpC44cudgnjZOQ1OCGjTwkwaGBon
GoSrpcVIQqmAj6LZftFBup9vWiUlUQdIDCbsQrsGZRJKBbOXyA++SlEsu6QjvQAAAABJRU5ErkJggg==
</value>
</data>
<data name="toolStripButton12.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE3SURBVDhPnZIxS8NQFEb7W/wLjh0Fl9a1SxBHBekkWFd1
qYg4Ci5dndSCg2AHl4LQSaRSKDqoFUE7VAjUmvTKueWmL2mw2gunL7zmO+/mJhmZoTJusdF868vpXUfO
b5/lpPEox9f3SvnsRtk8uojxHQ7HEgSEkXS6vrz3xqtdu+xdfUiheEBsJOGCk/mz/hROUHsIIrp+qIKY
hB/a9r+CVAG4Auj5g7iA5/1NACaptgIVLHkb0wWVw13ZL60p2+uerqkCJs1mMgwUU6d1k/xJwI10RZj1
9TPUN7Wam9dgTMC75QR7TjCBkRQs5Jd1jQS8c1ewtZLTPcQW/peADpC44cudgnjZOQ1OCGjTwkwaGBon
GoSrpcVIQqmAj6LZftFBup9vWiUlUQdIDCbsQrsGZRJKBbOXyA++SlEsu6QjvQAAAABJRU5ErkJggg==
</value>
</data>
<data name="toolStripButton13.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE3SURBVDhPnZIxS8NQFEb7W/wLjh0Fl9a1SxBHBekkWFd1
qYg4Ci5dndSCg2AHl4LQSaRSKDqoFUE7VAjUmvTKueWmL2mw2gunL7zmO+/mJhmZoTJusdF868vpXUfO
b5/lpPEox9f3SvnsRtk8uojxHQ7HEgSEkXS6vrz3xqtdu+xdfUiheEBsJOGCk/mz/hROUHsIIrp+qIKY
hB/a9r+CVAG4Auj5g7iA5/1NACaptgIVLHkb0wWVw13ZL60p2+uerqkCJs1mMgwUU6d1k/xJwI10RZj1
9TPUN7Wam9dgTMC75QR7TjCBkRQs5Jd1jQS8c1ewtZLTPcQW/peADpC44cudgnjZOQ1OCGjTwkwaGBon
GoSrpcVIQqmAj6LZftFBup9vWiUlUQdIDCbsQrsGZRJKBbOXyA++SlEsu6QjvQAAAABJRU5ErkJggg==
</value>
</data>
<data name="toolStripButton5.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE3SURBVDhPnZIxS8NQFEb7W/wLjh0Fl9a1SxBHBekkWFd1
qYg4Ci5dndSCg2AHl4LQSaRSKDqoFUE7VAjUmvTKueWmL2mw2gunL7zmO+/mJhmZoTJusdF868vpXUfO
b5/lpPEox9f3SvnsRtk8uojxHQ7HEgSEkXS6vrz3xqtdu+xdfUiheEBsJOGCk/mz/hROUHsIIrp+qIKY
hB/a9r+CVAG4Auj5g7iA5/1NACaptgIVLHkb0wWVw13ZL60p2+uerqkCJs1mMgwUU6d1k/xJwI10RZj1
9TPUN7Wam9dgTMC75QR7TjCBkRQs5Jd1jQS8c1ewtZLTPcQW/peADpC44cudgnjZOQ1OCGjTwkwaGBon
GoSrpcVIQqmAj6LZftFBup9vWiUlUQdIDCbsQrsGZRJKBbOXyA++SlEsu6QjvQAAAABJRU5ErkJggg==
</value>
</data>
<data name="toolStripButton14.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE3SURBVDhPnZIxS8NQFEb7W/wLjh0Fl9a1SxBHBekkWFd1
qYg4Ci5dndSCg2AHl4LQSaRSKDqoFUE7VAjUmvTKueWmL2mw2gunL7zmO+/mJhmZoTJusdF868vpXUfO
b5/lpPEox9f3SvnsRtk8uojxHQ7HEgSEkXS6vrz3xqtdu+xdfUiheEBsJOGCk/mz/hROUHsIIrp+qIKY
hB/a9r+CVAG4Auj5g7iA5/1NACaptgIVLHkb0wWVw13ZL60p2+uerqkCJs1mMgwUU6d1k/xJwI10RZj1
9TPUN7Wam9dgTMC75QR7TjCBkRQs5Jd1jQS8c1ewtZLTPcQW/peADpC44cudgnjZOQ1OCGjTwkwaGBon
GoSrpcVIQqmAj6LZftFBup9vWiUlUQdIDCbsQrsGZRJKBbOXyA++SlEsu6QjvQAAAABJRU5ErkJggg==
</value>
</data>
<data name="toolStripButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE3SURBVDhPnZIxS8NQFEb7W/wLjh0Fl9a1SxBHBekkWFd1
qYg4Ci5dndSCg2AHl4LQSaRSKDqoFUE7VAjUmvTKueWmL2mw2gunL7zmO+/mJhmZoTJusdF868vpXUfO
b5/lpPEox9f3SvnsRtk8uojxHQ7HEgSEkXS6vrz3xqtdu+xdfUiheEBsJOGCk/mz/hROUHsIIrp+qIKY
hB/a9r+CVAG4Auj5g7iA5/1NACaptgIVLHkb0wWVw13ZL60p2+uerqkCJs1mMgwUU6d1k/xJwI10RZj1
9TPUN7Wam9dgTMC75QR7TjCBkRQs5Jd1jQS8c1ewtZLTPcQW/peADpC44cudgnjZOQ1OCGjTwkwaGBon
GoSrpcVIQqmAj6LZftFBup9vWiUlUQdIDCbsQrsGZRJKBbOXyA++SlEsu6QjvQAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="toolStripButton9.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="toolStripButton9.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE3SURBVDhPnZIxS8NQFEb7W/wLjh0Fl9a1SxBHBekkWFd1 YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEwSURBVDhPpZIxSwNBEIXzW/wLKS0Fm2ib5hBLBbESjG20
qYg4Ci5dndSCg2AHl4LQSaRSKDqoFUE7VAjUmvTKueWmL2mw2gunL7zmO+/mJhmZoTJusdF868vpXUfO UUQsBRtbKzVgIWhhIwhWIhFBtFAjgqaIcKDmLiPfwO7NXg6NZuDdLnv3vn03uyX5R5VssdB8+ZC9q5Yc
b5/lpPEox9f3SvnsRtk8uojxHQ7HEgSEkXS6vrz3xqtdu+xdfUiheEBsJOGCk/mz/hROUHsIIrp+qIKY XD7K7sW9bJ9eq1b3z1WLW4eBumkvgwDADKTVjuW1k41ubrV2/CbV+Y0sCRN25uXZQ9qnk7vEqx2nCggg
hB/a9r+CVAG4Auj5g7iA5/1NACaptgIVLHkb0wWVw13ZL60p2+uerqkCJs1mMgwUU6d1k/xJwI10RZj1 PIgdfyZ95jwEAOrEXyGA//0JYCGNm0QBk9HC74CdzRVZr82q6nORjoUAOs1i3owouk50BxkIwIekwsz4
9TPUN7Wam9dgTMC75QR7TjCBkRQs5Jd1jQS8c1ewtZLTPcQW/peADpC44cudgnjZOQ1OCGjTwkwaGBon /J7qSc1UymoMAJwtO9iOO4BTHjA2MRUCOHMLWJqu6BpgZ/4TgARArPlouSrR6EgxgJj2qBBNY0cnzI3a
GoSrpcVIQqmAj6LZftFBup9vWiUlUQdIDCbsQrsGZRJKBbOXyA++SlEsu6QjvQAAAABJRU5ErkJggg== uId4AJeiefukjbTXt6jyEJ8AiBMdtiKuk4V4wDD1Db5KUSxr13uqAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="toolStripButton3.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="toolStripButton3.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw /aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D 1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC
TgDQASA1MVpwzwAAAABJRU5ErkJggg== nOccAdABIDXXE1nzAAAAAElFTkSuQmCC
</value>
</data>
<metadata name="dsMSSQL.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="toolStripButton10.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAL4SURBVDhPhdHrT1JxHMdxHtWf0KwHPXRrBStatXpQkhpq
m91MXZmiiK4buaTZltGIlqk0rQlbNaer9aCadkG8YBdABBZ0UVQqb4C6ZZHK5Rw859CnnYNhtrV+23vn
we/8Xtv39+PxeDxe2iVT0f46uzG73v4jXWknsuvtJJeG/TrI7DobmXnD6t6lsDRuyHm0ij2zYmVc67PM
BsnvbrebCYSjCISW+x5kIzEyE0T1cx/y6z0R8RnD6hVAVo111u0eYmyTFBxeGg4fDfskDevEIkxfouga
DiNKA3oPgeqnXpTcchMrkHRlF7EQWYTLz+Cdn4bLT+MthyzCPBpFz3AEUToG1wwDxzQFtcEH0cVXD7nD
eZqU8aPKnJ8y7WGUNB1BU3crrrZpIFLykaLkQ6zeiTTVNjToG7hRQiSNr3MRpBWaaQ7IrRM9eTXYgY7P
99Bkr+SQwtuZqHxQgLOt+ZDqDqBYVwz9x6/ocIfwYmAB8+Eo0lV9JAeIG8Wr+Uo5Y//0BvcHVag1neGQ
Im0WpLqDKL9TBstomBvl5WcCRg+BuTCF9Kv9cYBdGTVmsqJZAueoFTrHBVzvPY88zV4U3c6BczICp5cG
e8GWsfidBMIU0lR/ALsvK6ntVetR0CiGa8wG9ZuTUBkqkH8zFa2mZ/gwRcPpp2GboNA/QWE2SEF0ZQnY
okiSCRXrcLblGI5rM3CsYR+HVBgKoGgrQ54mFey+y8fgLfvEXhpBkoZAbo0DQsWaKaFiLYSKJAgrk3Co
NhWn7kpgGTZCbazCyccSSLW5cPoYOCZp2L00SCoGgdy0PMIeeR85M0/i4xTDZf40jXPN5SjV5kKmy8f5
ltOJPbbIIgOBvH0ZYDV/YBn4X2F2hLI/gB0VryM9/R9+/v3jvxoc9sQ2FepDCWBLee+4dyESfG0biI1/
IzA+S2B0qW8hiou9+RDJ4P3gSIwgiPnkE51DCWBrefcpgbSrd7PMGBDI2slEpfH4v5O2k8nSzrmNxZ0v
+RJDCXv2F6ujnydZP57oAAAAAElFTkSuQmCC
</value>
</data>
<data name="toolStripButton11.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEwSURBVDhPpZIxSwNBEIXzW/wLKS0Fm2ib5hBLBbESjG20
UUQsBRtbKzVgIWhhIwhWIhFBtFAjgqaIcKDmLiPfwO7NXg6NZuDdLnv3vn03uyX5R5VssdB8+ZC9q5Yc
XD7K7sW9bJ9eq1b3z1WLW4eBumkvgwDADKTVjuW1k41ubrV2/CbV+Y0sCRN25uXZQ9qnk7vEqx2nCggg
PIgdfyZ95jwEAOrEXyGA//0JYCGNm0QBk9HC74CdzRVZr82q6nORjoUAOs1i3owouk50BxkIwIekwsz4
/J7qSc1UymoMAJwtO9iOO4BTHjA2MRUCOHMLWJqu6BpgZ/4TgARArPlouSrR6EgxgJj2qBBNY0cnzI3a
uId4AJeiefukjbTXt6jyEJ8AiBMdtiKuk4V4wDD1Db5KUSxr13uqAAAAAElFTkSuQmCC
</value>
</data>
<data name="toolStripButton12.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEwSURBVDhPpZIxSwNBEIXzW/wLKS0Fm2ib5hBLBbESjG20
UUQsBRtbKzVgIWhhIwhWIhFBtFAjgqaIcKDmLiPfwO7NXg6NZuDdLnv3vn03uyX5R5VssdB8+ZC9q5Yc
XD7K7sW9bJ9eq1b3z1WLW4eBumkvgwDADKTVjuW1k41ubrV2/CbV+Y0sCRN25uXZQ9qnk7vEqx2nCggg
PIgdfyZ95jwEAOrEXyGA//0JYCGNm0QBk9HC74CdzRVZr82q6nORjoUAOs1i3owouk50BxkIwIekwsz4
/J7qSc1UymoMAJwtO9iOO4BTHjA2MRUCOHMLWJqu6BpgZ/4TgARArPlouSrR6EgxgJj2qBBNY0cnzI3a
uId4AJeiefukjbTXt6jyEJ8AiBMdtiKuk4V4wDD1Db5KUSxr13uqAAAAAElFTkSuQmCC
</value>
</data>
<data name="toolStripButton13.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEwSURBVDhPpZIxSwNBEIXzW/wLKS0Fm2ib5hBLBbESjG20
UUQsBRtbKzVgIWhhIwhWIhFBtFAjgqaIcKDmLiPfwO7NXg6NZuDdLnv3vn03uyX5R5VssdB8+ZC9q5Yc
XD7K7sW9bJ9eq1b3z1WLW4eBumkvgwDADKTVjuW1k41ubrV2/CbV+Y0sCRN25uXZQ9qnk7vEqx2nCggg
PIgdfyZ95jwEAOrEXyGA//0JYCGNm0QBk9HC74CdzRVZr82q6nORjoUAOs1i3owouk50BxkIwIekwsz4
/J7qSc1UymoMAJwtO9iOO4BTHjA2MRUCOHMLWJqu6BpgZ/4TgARArPlouSrR6EgxgJj2qBBNY0cnzI3a
uId4AJeiefukjbTXt6jyEJ8AiBMdtiKuk4V4wDD1Db5KUSxr13uqAAAAAElFTkSuQmCC
</value>
</data>
<data name="toolStripButton5.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEwSURBVDhPpZIxSwNBEIXzW/wLKS0Fm2ib5hBLBbESjG20
UUQsBRtbKzVgIWhhIwhWIhFBtFAjgqaIcKDmLiPfwO7NXg6NZuDdLnv3vn03uyX5R5VssdB8+ZC9q5Yc
XD7K7sW9bJ9eq1b3z1WLW4eBumkvgwDADKTVjuW1k41ubrV2/CbV+Y0sCRN25uXZQ9qnk7vEqx2nCggg
PIgdfyZ95jwEAOrEXyGA//0JYCGNm0QBk9HC74CdzRVZr82q6nORjoUAOs1i3owouk50BxkIwIekwsz4
/J7qSc1UymoMAJwtO9iOO4BTHjA2MRUCOHMLWJqu6BpgZ/4TgARArPlouSrR6EgxgJj2qBBNY0cnzI3a
uId4AJeiefukjbTXt6jyEJ8AiBMdtiKuk4V4wDD1Db5KUSxr13uqAAAAAElFTkSuQmCC
</value>
</data>
<data name="toolStripButton14.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEwSURBVDhPpZIxSwNBEIXzW/wLKS0Fm2ib5hBLBbESjG20
UUQsBRtbKzVgIWhhIwhWIhFBtFAjgqaIcKDmLiPfwO7NXg6NZuDdLnv3vn03uyX5R5VssdB8+ZC9q5Yc
XD7K7sW9bJ9eq1b3z1WLW4eBumkvgwDADKTVjuW1k41ubrV2/CbV+Y0sCRN25uXZQ9qnk7vEqx2nCggg
PIgdfyZ95jwEAOrEXyGA//0JYCGNm0QBk9HC74CdzRVZr82q6nORjoUAOs1i3owouk50BxkIwIekwsz4
/J7qSc1UymoMAJwtO9iOO4BTHjA2MRUCOHMLWJqu6BpgZ/4TgARArPlouSrR6EgxgJj2qBBNY0cnzI3a
uId4AJeiefukjbTXt6jyEJ8AiBMdtiKuk4V4wDD1Db5KUSxr13uqAAAAAElFTkSuQmCC
</value>
</data>
<data name="toolStripButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEwSURBVDhPpZIxSwNBEIXzW/wLKS0Fm2ib5hBLBbESjG20
UUQsBRtbKzVgIWhhIwhWIhFBtFAjgqaIcKDmLiPfwO7NXg6NZuDdLnv3vn03uyX5R5VssdB8+ZC9q5Yc
XD7K7sW9bJ9eq1b3z1WLW4eBumkvgwDADKTVjuW1k41ubrV2/CbV+Y0sCRN25uXZQ9qnk7vEqx2nCggg
PIgdfyZ95jwEAOrEXyGA//0JYCGNm0QBk9HC74CdzRVZr82q6nORjoUAOs1i3owouk50BxkIwIekwsz4
/J7qSc1UymoMAJwtO9iOO4BTHjA2MRUCOHMLWJqu6BpgZ/4TgARArPlouSrR6EgxgJj2qBBNY0cnzI3a
uId4AJeiefukjbTXt6jyEJ8AiBMdtiKuk4V4wDD1Db5KUSxr13uqAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<metadata name="cm.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="cm.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
@@ -400,9 +402,9 @@
<value>499, 17</value> <value>499, 17</value>
</metadata> </metadata>
<metadata name="fpSpread1_Sheet1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="fpSpread1_Sheet1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>563, 17</value> <value>561, 17</value>
</metadata> </metadata>
<data name="dateTimeCellType1.Calendar" mimetype="application/x-microsoft.net.object.binary.base64"> <data name="dateTimeCellType3.Calendar" mimetype="application/x-microsoft.net.object.binary.base64">
<value> <value>
AAEAAAD/////AQAAAAAAAAAEAQAAACZTeXN0ZW0uR2xvYmFsaXphdGlvbi5HcmVnb3JpYW5DYWxlbmRh AAEAAAD/////AQAAAAAAAAAEAQAAACZTeXN0ZW0uR2xvYmFsaXphdGlvbi5HcmVnb3JpYW5DYWxlbmRh
cgYAAAAGbV90eXBlEW1fY3VycmVudEVyYVZhbHVlD3R3b0RpZ2l0WWVhck1heBpDYWxlbmRhcittX2N1 cgYAAAAGbV90eXBlEW1fY3VycmVudEVyYVZhbHVlD3R3b0RpZ2l0WWVhck1heBpDYWxlbmRhcittX2N1
@@ -412,7 +414,7 @@
AAD/////AQgAAP////8AAQgAAAs= AAD/////AQgAAP////8AAQgAAAs=
</value> </value>
</data> </data>
<data name="dateTimeCellType2.Calendar" mimetype="application/x-microsoft.net.object.binary.base64"> <data name="dateTimeCellType4.Calendar" mimetype="application/x-microsoft.net.object.binary.base64">
<value> <value>
AAEAAAD/////AQAAAAAAAAAEAQAAACZTeXN0ZW0uR2xvYmFsaXphdGlvbi5HcmVnb3JpYW5DYWxlbmRh AAEAAAD/////AQAAAAAAAAAEAQAAACZTeXN0ZW0uR2xvYmFsaXphdGlvbi5HcmVnb3JpYW5DYWxlbmRh
cgYAAAAGbV90eXBlEW1fY3VycmVudEVyYVZhbHVlD3R3b0RpZ2l0WWVhck1heBpDYWxlbmRhcittX2N1 cgYAAAAGbV90eXBlEW1fY3VycmVudEVyYVZhbHVlD3R3b0RpZ2l0WWVhck1heBpDYWxlbmRhcittX2N1
@@ -428,90 +430,89 @@
<data name="toolStripButton8.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="toolStripButton8.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAANPSURBVFhH7dhZTxNRHAVwPoRx3yuyKWUvqyJu4BqNiYnx YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAANNSURBVFhH7dhnT1NRHAZwPoRx74osZZTRUkARFzijMTEx
C/giaowRQSiibC0Uyg6CyqKSuEaEQvdCK7tPqAmokWDUiFGgyCrHO+k0oT609w4JvvQk9/n+MjPn/ifX fgHfiBpjRBCKIKuFQtkgoEBVElwRoaWTLkahvkJNQI0Eg0aMsqc85ia24TYBzrkk+KbPJ/jl3Puc/8nf
wx133BGQh8dfX3hwzGy9f7QfDUfIOtyH+kN9qEvoRW18L+4d7MHdAz24s5+sfd2o2duN6rgu3N7TharY w8Mdd9yhz9Ozb689OWMZf3zaDsUpOxQne1B/ogd1cd2oje3Go+M2PDxmQ81RG2qOdKH6cBeqYjrx4FAn
TlTu7kTFrlcojyEr2oKyKAtKIy0oiTCjONyMIkkHlGFkhbajMKQdBcEma36QIZHf3nWWGQdFkAm5gaYJ KqM7UHGwA+UH2lEW1Y6ySCtKI6woEVlRHG5BkdCCQoEZ8jAz5KEmFISYkB9sHM/jG+JdHUtmjXGQ8Y3I
fnvXWW5cfqAJeQFG8Nu7zv/AycUswCXgyqLNUEbokSdpQ4FEh6LwDiqc3N9AD1zKkyuM1KL/8UfMTs2j CTKOuTqWzFrj8oKMyA1sg6tjyfwPnDSABrgKXGmkBfJwPXIFrcgX6FAoNBPhpP4GciBXHHNyBSIt7M8+
p/ED5CEaKpxsJwNQKI57cu2V77A4xfFaKlzuDj09UAiuONKER5e6sfBngacBP0cmIQtTUeFy/BiArLjS Y3ZqHraGT5CGaIhwkv0UQK445uRMFR+wOEWxWiJczj49OZALrkhkROONLiz8WXDifg1OQBKmJMJl+1EA
qA5UnTJgemKWpwFzM/OoOWuEIthIhcv21dED2XCkFLFafH8/ztNseSHtR16wjhqX5cMApMVxR4kiXIO3 aXElEWZUXjBgemzWiZubmUf15TbIgtuIcFm+OnIgHc4CebQWPz6OOnFMXovtyA3WEeMyfSiApDjmKpEJ
ms88y5auhiFy8KqZcJneLEBKXGG4HqYKx1IM94+S766VGZfppaUH0uCKIkgpLjqWYuzLbxTGqcl3Z2DG NXiv+crCdSr6kROkpsJleNMACXEFQj2M5exSDNiHIQlTUeMyvLTkQBJcYbgRjdfZpRgZmkRBjBqyYAM1
3drOAHSFK4nkS2Gd42m2UlSfMYIMfUG4m54aeqAzHDe+FGE6DHV85Wm2PEvpgzxIKxiXsY0B6AzHzdb8 7v5eCuBKuGLRv1KMzzlxTCmqLrUhj88Nl+6pIQcuh2PGlyxMh37zNyeOycukHkj5Ws64tD0UwOVwzGzN
UB0G2x2BT5N7IQvUCsbdEKnpgc5w3OBXSkwoP6F3fMXT86g8TUBivSBc+lYGoDOcffArQvRoTOxyKMkv C9Whz8QGvkjshiRIyxl3j6cmBy6HYwa/XGBE2Tk9+xNPz6PiogGSAD0nXOpuCuByOMfgl4Xo0RDfySrJ
UhJ5TCtk/jpmnHRLGz3QFc4+W2VBGuhL3/A8Wz71jSJT3MyMS9vMAqTA2c+5LLEKA20jPM8WS+0gMnxb 76FJSKNUkPjrqHHiXa3kwJVwjtkq4WugL3nnBDL50jOMjIBmalzKThogAc5xz2UGKNHbOshCWmv7kObb
mHBpm1rpgbQ4rhDyAANyJCp8GxrjebY8SepBhncrNS51IwOQFmdvK/fNKRM0mBpf9LNASlN6kqC81FS4 QoVL2aEiB5LimEJIAw3IFijxvX+EhXyeYEOat4oYl7ydAkiKc7SV+efkcRpMjS56LEzPo+S8FuleaiLc
6xsYgCw4e1uz/NSoP2d2KM2P4QlIfZqocCnrVfRAVpy9EBk+KmiUAzzPluyIFipc8joGoBCcvRBS75fo 3W0UQBqco62ZfmrUX7GwSvNzYAxinyYiXNJWJTmQFucoRJqPEhp5rxPIJCu8hQiXuIUCyAXnKITY+w06
JH8zM5NzsNQNIlXURIW7traFHigUZy+E1LMFKaLnBNeMdFEbFS5pDQtwCTjaQvyLS1rdTA/8H7irqxiA FP2YmZiDta4PybwmItydzS3kQK44RyHEni1I4r1CMq8ZqbxWIlzCJhrgKnCkhXDFJWxsJgf+D9ztDRRA
BGddbtzllU30Vx/cRQ53V7KcuCsrms7z27vjjjv08fD4CwlIPe+HvHrCAAAAAElFTkSuQmCC Zley1rib65vIVx/MIofZlawl7ta6pquuDnfccYcgfwEJSD3vAJhh2AAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="toolStripButton7.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="toolStripButton7.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAANSSURBVFhH7djZTxNRGAVw/gjjvq9tVWgBAbUguO+aGE18 YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAANRSURBVFhH7dhZT5NBGAVgfoRx31daWVpAUCgI7uCaGE28
8N0XFROj4oYitHbB0haL4i4qGhUTRew27bS1pRSEJ4kkKCZuiRhJpEQE5TjDTKPEpL13TPClJ7nP95e5 8N4bFROjgqKApaVspQXZXZBNo2LiAm3pR7+2tpSW5UqCCQKJookYSaRGFOGYIWm1GGDmM4Gbnl/wZCZn
c+a7mZRkkklGQu5saSus3RyM3t7UilsbubXhOW6uf46adS24sbYF19c049rqZlxdxa2VEVxZEcHl5U24 3skbEOCPP/6w58HR7uSGIzZ3/eEu1B3qQt3BTtQmdaImsQP3D3Sger8L9/a5cHevC3f3OHFntxO3d7Wj
VNCEi/lhVC8L40JeI87ncksdQtXSEGxLQji3OIjKnCCs2c9gyeLWogDMmQFUZPijZ9PZfeL2iTPKOJjS KqEdlfEOVOx0oDyuDWWxbSiT2VEaY0dJtB23dthQvN2GoqhX0Ea+gnabFZoIKwrDLe6CMP78dMeMmWcc
/dCr/L3i9okz2rizKj/KlT6I2yfO/8AZ02iAhLiLBWHY8nwwq12oVLOoyg1JxhlTWXIg6ZOrzGXRer8L 1GEW5Egto9MdM2a+cQVSC/IlZkx3zJiFwOWFsgApcZUJDpTEmaGRtaBYxqM01i4YlxfC0wNpcOTkimN5
A99+oK3uDSxLGck4w0IKIPGxbmXxZwLVL2HO8UrC6Rd4yYGk75w1n0HP+z6RBwz9HMK9/RGYs33UON18 dD0ewM/vv9DdOAhtDCcYlxvMAKTBTV3rMR5/x1rRC812kyBcTpCJHkiF2+lAUTyHkaFvXuDkxCQeXXBC
CiBpIWzqIK7vCgwfcSzfo4Oo3s7CnOWnwp1ReMiBJLhYW61LfHh0vFXkCfn8phemPCcqMv3EOK2cAkiK E2Vmxqm2MgBpcKQQJTIbqk9bp67Ykx/ucVSc4KGJtDDhssWt9EAanKetRdFmPEvr8gJJPg+OQh1nQGGE
ixXClOVBpPaVyBPSwX6EPt1BjNPIaIAUuFghjNkOdEW6RZ4Qr60dOqWbCKeZx5ADaXF8IcxZ3LuW70TP hRqnFDEAaXGeQqgjW+FseOuDfMN/RE6YnhqnCGQBMuA8hciL0mPAOeyDNJX0QCUxUuEUWzh6ICuOFEIT
uz9KMwTcLQzjTKo7Ia5sLgWQFhdrqynDh0s7WQz2/y5Nf+8ArBvc0C/0xMWVznGTA6XgYm01qBg8PNIi aUVhvAEj7/8qzSTwMNmB7BDjnLiszQxAVpynrepwM6pO8Rgf+1OasdGfKDpoRE5w66w4+SYjPVAIztPW
8oR0+D6iVGGPizs9mwIoFccXQq9kUFc0EvjS+4EDOuLiSma5yIFScUYliws7vH8dsXmdC1oFExd3aiYF XCmHp6kdXiDJG/NHyMW6WXE3NzIAheKmfiUSDo0pvsBe0wfIxfpZcZkbWuiBQnF5Eh7lJ03/XLEmsQVK
UAquXOWDQW3Hl7dRkSaUpHZPI0rljoS4kzOc5EBaHP+d0ygb8DrySaQJYSwvcFpuJ8IVT6cBUuK0qU40 MTcrLmM9A1AILl9qRq5Mhy/v3F4cKUnD2TbIRfo5cenrDPRAVhx55xSSJvQ7P3lxJJz2NW6KdFS4G2tZ
3uwUWULamfcoUTwhxhVPc5ADaXC6NDceHGoWWUK6X3+FJrMBGjlDjDsxlQJIijOkeVG1zTvistDPXRYs gIw4ZYgBbbV9PrgebgiZ4pfUuBtr9PRAFpwq1Ignl10+uOH+r1BENEEh4qhx11czAGlxuaEmlB43+XwW
613UuONTKIAkOH58aVVPR5aCu27V7A6iVOakxh2bbCcHkuD42WoqcIo0IXwpSmR2SbijkyiAJDh+tpbN xtzj0Ca1MOPSVjEAaXBkfCmlzb6lmJhEzRkb5IEGZty1lTp6IA2OzFZ1gsGLIyGlyAzUCcJdXcEApMGR
t6Ppdie+9w0ifKsTp+RPJOOOTHxKDiTB8YNft8AzPCFOyh7/05PjcUUTaIAEuESDnxZXNL6BHPg/cIfH 2Zq1VYf2+j78+DYOR10fMkQvBeNSlzfTA2lwZPCrglqnJkR64PP/OjmCS1nGAqTAzTX4WXEpS5vogQuB
UQA5XHS0cQfG1pP/+uB/5PD/SkYTd3BM/V5x+2SSSYY8KSm/AHvBPpKbf2MsAAAAAElFTkSuQmCC u7KEAUh2JfONu7j4Bf3qgyxyyK5kPnGXFr04N93hjz/+UOQ3e8E+krxr0cIAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="toolStripButton4.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="toolStripButton4.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGJSURBVEhL7ZS9TsQwEITzeoBo4Dko6eiRDpAQ4i0oqWg5 YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFtSURBVEhL7ZQxTgMxEEVzPUA0cA5KOnqkABJC3IKSipZA
aICXoKKjpTQMmgkTs+tLQuhupJHXPzuffYqu22qszta7BeZ0eUXhgsLnD3u/9lf3O3+/kENghPocYKyt A1yCio42pdGs+Ku/b2ezdggVfGlkx/b857G9WSz+VamL1X6J4PjOlJkLGnH5dDCaXz7ujcaa5ZCIMCU4
uKc52+fLIZF72FctaPQrTBJCIpjbYT7CjJkmNUcwt8Nmw3EwCm+5BUU9+hJReMsOw3jxuF9u347L9fPh xpbfc/pNn2YRzOhhtonsFJrE6rJwmLdbV61kghgZtBleA2IQ5tDoV2+CxnNB6NXzYbn/OC23r8dtd07j
YJ3xuaLwlv1FgN69n5SXclnWH6fl6umg32d8rii8ZX+poDBqrP3rizMo9ka9OAre5NZLZcBxlpih/ICM ufCKAvrweVbeynVZrc/LzctRP0/OSDSeC69U0Ijox9ivVjwF9TsmZyCa1sQUVMevimMteZ18gUL3psdS
NYToY/E9OIWyV69VLmrifqTDHowGBeNjcXjrpehzqI/EDfUNJ1CHb16P+nDBM2gG00hMrKiphi/2Ulfd DU0enfzIXWixG0eCPxaHT0LxGbElt1MHx7d5937Smws+BSWELXkDcXEGz6BbVepikvoOn4JGy3y15IzE
pNrhGRRj3a+R8bnqJq8d7j+v93itfpxjfC5vwugfGwy4oJhHoKif8bFwsA5So4w1QTX3nqwfNTFt4aA3 JO87PPtk2Fd+rCNnJO6ULzngguoBEpTlkzNQtmOCVYH/3lSxryMvlXZPMIMgr7waRtWAM6ha+jWJhgTz
Zq5BGmXGTRMaI5jbYfXImHmqA2sw1qJ9ts+XQhGGUbWstfqfj+3zFYUoHMbFuNwLF2C5vATmdKsN6rpP eDVOn2b5XWXH3x8r/vno06zMhBVz/sfHvEk7q+zP6At9mNZRIJ9c/gAAAABJRU5ErkJggg==
fZjWUaDH7j0AAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="btSearch.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="btSearch.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE4SURBVDhPtZPPasJAEMbzPn0FwWA92JtP4NGKB1/DP7ei YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEiSURBVDhPY2DAAf6jAXRxVNVIAKYga5bH/7TpTmAMYsNA
QSsovkChh7ZBrCfpyR4sikopUgq9StFzM/UbZ5asSS4FfzAkO7vft5udiZMEnSBpk5dhFJmncjdHxXaG 3EQb3Ab8+/fv/71PZ/5nzXX+f+3T7v+X320H0yCct8Dz/9rTM/8HtGvDDcPQDAIgBSCNOx9NBuOOiw7/
A+9K4SbFT1luEwQBbXavVO5d0nI3ovnW5yeiMriiu+kt5asXbABEdgRigAUQDr+aHLU3lxoLl/yPJhvF u644/N9+ZzLYIKwGwARAkvP2dIJpGN52Y/r/9gsO/zuu2P/f+3Qq3ACQhVhtz5jlBLcBJnb43Qyw5p0P
GsiYJ/vPdX5qPK3bVJ25VFukafztGQNsKHJ791I3w+8KcpNth8XDz5YxACI/gsR1J8sTYcO4UIzwv1gG pmB3AcwV6TNcwBLIBmLDKAbAeWQAFAPQbUG2DeYimAsxnA4z4PLnDWD/Hv2AGl0gAAobZAOxGgDSCApt
cTshgJ5IT8hChTMHsHi+v+fvffmxywVwN2FDkdsGEOK2ceu4feQ0tDqKyKMGqDfqjvprLzyswuX7Tf4E UKiDQh/ZJbDYgQGcBoDiGxTvoPiHpYUt15Gj7y9uL4BSGijFbb81FYy33pgK1gxKyqAUiuJ0ZAAyAJbG
dBo6zn/3OB7XHovRyuhQ6+hhYKA9DpL+A1keRebNAhkaJH0OHOcP031C4EjYr6wAAAAASUVORK5CYII= QQBXPkDXBwfoCuA60MRpAgDTfULg/+7qPQAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="toolStripButton2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="toolStripButton2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADlSURBVEhL7dQxCsIwFMbxnMrZWatzUXRUCo5ewSs4ewZR YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADiSURBVEhL7dVBCsIwEAXQnsq1a62ui6JLpeDSK3gF155B
DyDeQfEETsUbRL7YYNSXNC/UOiQP/kvzyE9KUcQ7y/VJtlHFvQYPjzf50xKsJsFmq81WHq538swMO9il 1AOId1A8gSvxBiNTCcTJJM3E2i6SwN9MhnklDW2WRbvW2wu0EepW8PkBf02CE2xks9vD6f4y6jTYg720
zhALxkWd7kAOJwsnjjPsYNeGs2B14fR5YTYq5O5c1u7sL987iAUjF+6LIjaMKJyDoiAYmVAvn8lsXHij riKCcVCvP4LxbOXEcQ97sNeGi+Bq4PwzMJ+UcLg+a3uON7NHDHODdZzu2dAgmAMQpzUXGgxTfFAsIJ+W
KBhGwDWof4APihqHqQ+OKhg2X3U/n7+9ah88CKY+pM9ndTgbplDbmQtnwS7UtmPDWfDf/jIRLnKhOuzY 3uhPMAZxBaoH8EExjcPcheMSDOtHPSyWX0ftgwfB3EWitTpcDFNAf6d0z4WLYDqYu0i0x4aL4M4+mZhO
UMSGmyrBauKE26jiohshHicE2B3dbRrmAAAAAElFTkSuQmCC fhJNJsERw22EuvGsNycE2B33w41tAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="toolStripButton6.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="toolStripButton6.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw /aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D 1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC
TgDQASA1MVpwzwAAAABJRU5ErkJggg== nOccAdABIDXXE1nzAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
</root> </root>

View File

@@ -38,13 +38,13 @@
System.Windows.Forms.Label label5; System.Windows.Forms.Label label5;
System.Windows.Forms.Label label3; System.Windows.Forms.Label label3;
System.Windows.Forms.Label label6; System.Windows.Forms.Label label6;
System.Windows.Forms.Label label2;
System.Windows.Forms.Label label7; System.Windows.Forms.Label label7;
System.Windows.Forms.Label label8; System.Windows.Forms.Label label8;
System.Windows.Forms.Label label9; System.Windows.Forms.Label label9;
System.Windows.Forms.Label label10; System.Windows.Forms.Label label10;
System.Windows.Forms.Label label11; System.Windows.Forms.Label label11;
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(fJobReport_Add)); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(fJobReport_Add));
this.label2 = new System.Windows.Forms.Label();
this.lbSummary = new System.Windows.Forms.Label(); this.lbSummary = new System.Windows.Forms.Label();
this.tbHrs = new System.Windows.Forms.TextBox(); this.tbHrs = new System.Windows.Forms.TextBox();
this.bs = new System.Windows.Forms.BindingSource(this.components); this.bs = new System.Windows.Forms.BindingSource(this.components);
@@ -93,7 +93,6 @@
label5 = new System.Windows.Forms.Label(); label5 = new System.Windows.Forms.Label();
label3 = new System.Windows.Forms.Label(); label3 = new System.Windows.Forms.Label();
label6 = new System.Windows.Forms.Label(); label6 = new System.Windows.Forms.Label();
label2 = new System.Windows.Forms.Label();
label7 = new System.Windows.Forms.Label(); label7 = new System.Windows.Forms.Label();
label8 = new System.Windows.Forms.Label(); label8 = new System.Windows.Forms.Label();
label9 = new System.Windows.Forms.Label(); label9 = new System.Windows.Forms.Label();
@@ -204,12 +203,12 @@
// //
// label2 // label2
// //
label2.AutoSize = true; this.label2.AutoSize = true;
label2.Location = new System.Drawing.Point(160, 163); this.label2.Location = new System.Drawing.Point(160, 163);
label2.Name = "label2"; this.label2.Name = "label2";
label2.Size = new System.Drawing.Size(53, 12); this.label2.Size = new System.Drawing.Size(53, 12);
label2.TabIndex = 21; this.label2.TabIndex = 21;
label2.Text = "초과시간"; this.label2.Text = "초과시간";
// //
// label7 // label7
// //
@@ -499,7 +498,7 @@
this.panel1.Controls.Add(this.tbProject); this.panel1.Controls.Add(this.tbProject);
this.panel1.Controls.Add(projectLabel); this.panel1.Controls.Add(projectLabel);
this.panel1.Controls.Add(this.tbHrs); this.panel1.Controls.Add(this.tbHrs);
this.panel1.Controls.Add(label2); this.panel1.Controls.Add(this.label2);
this.panel1.Controls.Add(this.lbTitleTip); this.panel1.Controls.Add(this.lbTitleTip);
this.panel1.Controls.Add(hrsLabel); this.panel1.Controls.Add(hrsLabel);
this.panel1.Controls.Add(this.chkAutoAdd); this.panel1.Controls.Add(this.chkAutoAdd);
@@ -671,7 +670,9 @@
// //
// tam // tam
// //
this.tam.AuthTableAdapter = null;
this.tam.BackupDataSetBeforeUpdate = false; this.tam.BackupDataSetBeforeUpdate = false;
this.tam.EETGW_DocuFormTableAdapter = null;
this.tam.EETGW_JobReport_AutoInputTableAdapter = null; this.tam.EETGW_JobReport_AutoInputTableAdapter = null;
this.tam.EETGW_JobReport_EBoardTableAdapter = null; this.tam.EETGW_JobReport_EBoardTableAdapter = null;
this.tam.EETGW_NoteTableAdapter = null; this.tam.EETGW_NoteTableAdapter = null;
@@ -758,5 +759,6 @@
private System.Windows.Forms.Button cmbTypeFull; private System.Windows.Forms.Button cmbTypeFull;
private System.Windows.Forms.ComboBox tbJobGrp; private System.Windows.Forms.ComboBox tbJobGrp;
private System.Windows.Forms.ComboBox tbJobType; private System.Windows.Forms.ComboBox tbJobType;
private System.Windows.Forms.Label label2;
} }
} }

View File

@@ -352,6 +352,11 @@ namespace FPJ0000.JobReport_
if (ReadMode) if (ReadMode)
{ {
//개인정보패치 251111
label2.Visible = false;
tbOt.Visible = false;
panel1.Enabled = false; panel1.Enabled = false;
this.Text += "(읽기전용)"; this.Text += "(읽기전용)";
} }

View File

@@ -147,9 +147,6 @@
<metadata name="label6.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="label6.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
<metadata name="label2.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="label7.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="label7.GenerateMember" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value> <value>False</value>
</metadata> </metadata>
@@ -175,9 +172,8 @@
<value>299, 17</value> <value>299, 17</value>
</metadata> </metadata>
<data name="richTextBoxEx1.Rtf" xml:space="preserve"> <data name="richTextBoxEx1.Rtf" xml:space="preserve">
<value>{\rtf1\ansi\ansicpg1252\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\froman\fcharset129 \'b8\'bc\'c0\'ba \'b0\'ed\'b5\'f1;}} <value>{\rtf1\ansi\ansicpg1252\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\froman\fcharset129 \'b8\'bc\'c0\'ba \'b0\'ed\'b5\'f1;}}
{\*\generator Riched20 10.0.22621}\viewkind4\uc1 \viewkind4\uc1\pard\lang1042\fs20 3. \f1\'c7\'c1\'b7\'ce\'c1\'a7\'c6\'ae\lang1033\f0 \f1\'c1\'a6\'b8\'f1\'c0\'ba\f0 (\f1\'b0\'f8\'c0\'e5\'b6\'f3\'c0\'ce\f0 ,PKG\f1\'b0\'f8\'c1\'a4\f0 /\f1\'c0\'e5\'ba\'f1\'b8\'ed\f0 \f1\'c1\'a6\'c1\'b6\'bb\'e7\f0 /\f1\'b8\'f0\'b5\'a8\'b8\'ed\f0 \f1\'c0\'e5\'ba\'f1\'b9\'f8\'c8\'a3\f0 \f1\'c1\'f6\'bf\'f8\'b3\'bb\'bf\'eb\f0 ) \f1\'c7\'fc\'bd\'c4\'c0\'b8\'b7\'ce\f0 \f1\'c0\'db\'bc\'ba\'c7\'d8\f0 \f1\'c1\'d6\'bc\'bc\'bf\'e4\f0 .\lang1042\par
\pard\fs20\lang1042 3. \f1\'c7\'c1\'b7\'ce\'c1\'a7\'c6\'ae\f0\lang1033 \f1\'c1\'a6\'b8\'f1\'c0\'ba\f0 (\f1\'b0\'f8\'c0\'e5\'b6\'f3\'c0\'ce\f0 ,PKG\f1\'b0\'f8\'c1\'a4\f0 /\f1\'c0\'e5\'ba\'f1\'b8\'ed\f0 \f1\'c1\'a6\'c1\'b6\'bb\'e7\f0 /\f1\'b8\'f0\'b5\'a8\'b8\'ed\f0 \f1\'c0\'e5\'ba\'f1\'b9\'f8\'c8\'a3\f0 \f1\'c1\'f6\'bf\'f8\'b3\'bb\'bf\'eb\f0 ) \f1\'c7\'fc\'bd\'c4\'c0\'b8\'b7\'ce\f0 \f1\'c0\'db\'bc\'ba\'c7\'d8\f0 \f1\'c1\'d6\'bc\'bc\'bf\'e4\f0 .\lang1042\par
} }
</value> </value>
</data> </data>

View File

@@ -32,7 +32,8 @@ namespace FPJ0000.JobReport_
if (tbProcess.SelectedIndex < 0) tbProcess.SelectedIndex = 0; if (tbProcess.SelectedIndex < 0) tbProcess.SelectedIndex = 0;
this.tbMon.Text = DateTime.Now.Year.ToString(); this.tbMon.Text = DateTime.Now.Year.ToString();
var curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
if (curLevel < 5) tbProcess.Enabled = false;
refrehData(); refrehData();
} }
@@ -70,12 +71,13 @@ namespace FPJ0000.JobReport_
this.dataGridView1.Columns.Add(drYm.yymm, drYm.yymm.Substring(0, 7) + "\r\n(" + basehr.ToString() + ")"); this.dataGridView1.Columns.Add(drYm.yymm, drYm.yymm.Substring(0, 7) + "\r\n(" + basehr.ToString() + ")");
} }
var curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
//이름으로 정렬해서 데이터를 가져온다 //이름으로 정렬해서 데이터를 가져온다
var namelist = this.dsReport.jobReport.OrderBy(t => t.uname).GroupBy(t => t.uname); var namelist = this.dsReport.jobReport.OrderBy(t => t.uname).GroupBy(t => t.uname);
foreach (var uname in namelist) foreach (var uname in namelist)
{ {
var drName = uname.FirstOrDefault(); var drName = uname.FirstOrDefault();
if (curLevel < 5 && drName.uid != FCOMMON.info.Login.no) continue; //개인정보 251111
List<string> rowdata = new List<string>(); List<string> rowdata = new List<string>();
rowdata.Add(drName.uname + "(" + drName.uid + ")"); rowdata.Add(drName.uname + "(" + drName.uid + ")");

View File

@@ -12,14 +12,14 @@ namespace FPJ0000.JobReport_
{ {
public partial class rJobReportDay : fBase public partial class rJobReportDay : fBase
{ {
// Boolean binit = false; // Boolean binit = false;
public rJobReportDay(string baseday ) public rJobReportDay(string baseday)
{ {
InitializeComponent(); InitializeComponent();
this.WindowState = FormWindowState.Maximized; this.WindowState = FormWindowState.Maximized;
if (baseday.Length > 7) if (baseday.Length > 7)
tbMon.Text = baseday.Substring(0, 7); tbMon.Text = baseday.Substring(0, 7);
} }
private void rJobReport_Load(object sender, EventArgs e) private void rJobReport_Load(object sender, EventArgs e)
@@ -35,9 +35,12 @@ namespace FPJ0000.JobReport_
this.tbProcess.Text = FCOMMON.info.Login.process; this.tbProcess.Text = FCOMMON.info.Login.process;
if (tbProcess.SelectedIndex < 0) tbProcess.SelectedIndex = 0; if (tbProcess.SelectedIndex < 0) tbProcess.SelectedIndex = 0;
var curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
if (curLevel < 5) tbProcess.Enabled = false;
//this.tbMon.Text = DateTime.Now.ToString("yyyy-MM"); //this.tbMon.Text = DateTime.Now.ToString("yyyy-MM");
refrehData(); refrehData();
// binit = true; // binit = true;
} }
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
@@ -66,15 +69,15 @@ namespace FPJ0000.JobReport_
var Process = tbProcess.Text.Trim(); var Process = tbProcess.Text.Trim();
if (Process == "%" || tbProcess.SelectedIndex == 0) Process = ""; if (Process == "%" || tbProcess.SelectedIndex == 0) Process = "";
var wekklist = new string[] { "일","월","화","수","목","금","토" }; var wekklist = new string[] { "일", "월", "화", "수", "목", "금", "토" };
//날짜에 해당하는 열을 먼저 생성한다 //날짜에 해당하는 열을 먼저 생성한다
dataGridView1.Columns.Add("dvcu_damdang", "사원명"); dataGridView1.Columns.Add("dvcu_damdang", "사원명");
// dataGridView1.Columns.Add("dvcu_process", "공정"); // dataGridView1.Columns.Add("dvcu_process", "공정");
var daylist = dsReport.JobReportDay.OrderBy(t=>t.pdate).GroupBy(t => t.pdate); var daylist = dsReport.JobReportDay.OrderBy(t => t.pdate).GroupBy(t => t.pdate);
foreach (var dayitem in daylist) foreach (var dayitem in daylist)
{ {
var dtValue = DateTime.Parse(dayitem.Key); var dtValue = DateTime.Parse(dayitem.Key);
var week = wekklist[(int)dtValue.DayOfWeek]; var week = wekklist[(int)dtValue.DayOfWeek];
this.dataGridView1.Columns.Add("dvcu_pdate", dayitem.Key.Substring(8, 2) + "(" + week.ToString() + ")"); this.dataGridView1.Columns.Add("dvcu_pdate", dayitem.Key.Substring(8, 2) + "(" + week.ToString() + ")");
@@ -96,26 +99,29 @@ namespace FPJ0000.JobReport_
// this.dataGridView1.Columns.Add("dvcu_pdate", dayitem.Key.Substring(8, 2) ); // this.dataGridView1.Columns.Add("dvcu_pdate", dayitem.Key.Substring(8, 2) );
//} //}
this.dataGridView1.Columns[this.dataGridView1.Columns.Count -1].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; this.dataGridView1.Columns[this.dataGridView1.Columns.Count - 1].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
} }
dataGridView1.Columns.Add("dvcu_sum", "합계"); dataGridView1.Columns.Add("dvcu_sum", "합계");
this.dataGridView1.Columns[this.dataGridView1.Columns.Count - 1].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; this.dataGridView1.Columns[this.dataGridView1.Columns.Count - 1].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
var curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
foreach (var item in dsReport.JobReportDay.Where(t=>t.processs.Contains(Process)).OrderBy(t => t.uname + t.uid).GroupBy(t => t.uname)) foreach (var item in dsReport.JobReportDay.Where(t => t.processs.Contains(Process)).OrderBy(t => t.uname + t.uid).GroupBy(t => t.uname))
{ {
//사용자별로 데이터를 가져온다. //사용자별로 데이터를 가져온다.
var username = item.Key; var username = item.Key;
var userid = item.FirstOrDefault().uid; var userid = item.FirstOrDefault().uid;
if (curLevel < 5 && userid != FCOMMON.info.Login.no) continue;
List<string> rowdata = new List<string>(); List<string> rowdata = new List<string>();
rowdata.Add(username); rowdata.Add(username);
// rowdata.Add(item.FirstOrDefault().processs); // rowdata.Add(item.FirstOrDefault().processs);
//이 사용자의 데이터를 날짜별로 정렬해서 가져온다. //이 사용자의 데이터를 날짜별로 정렬해서 가져온다.
var sum = 0.0; var sum = 0.0;
var sumOT = 0.0; var sumOT = 0.0;
var sumFR = 0.0; //휴일근무시간 210310 var sumFR = 0.0; //휴일근무시간 210310
for (int i = 1; i < this.dataGridView1.Columns.Count-1; i++) for (int i = 1; i < this.dataGridView1.Columns.Count - 1; i++)
{ {
var col = this.dataGridView1.Columns[i]; var col = this.dataGridView1.Columns[i];
var dayStr = col.HeaderText.Substring(0, 2); var dayStr = col.HeaderText.Substring(0, 2);
@@ -133,15 +139,15 @@ namespace FPJ0000.JobReport_
{ {
//이날은 휴일이다 //이날은 휴일이다
sumFR += daydata.ot;// + daydata.hrs; sumFR += daydata.ot;// + daydata.hrs;
//sumOT += daydata.ot; //sumOT += daydata.ot;
rowdata.Add("*" + daydata.hrs.ToString() + "+" + daydata.ot.ToString()); rowdata.Add("*" + daydata.hrs.ToString() + "+" + daydata.ot.ToString());
} }
else else
{ {
//평일이다 //평일이다
sumOT += daydata.ot; sumOT += daydata.ot;
if(daydata.jobtype == "휴가") if (daydata.jobtype == "휴가")
{ {
if (daydata.hrs + daydata.ot == 8.0) rowdata.Add("휴가"); if (daydata.hrs + daydata.ot == 8.0) rowdata.Add("휴가");
else rowdata.Add((daydata.hrs.ToString() + "+" + daydata.ot.ToString())); else rowdata.Add((daydata.hrs.ToString() + "+" + daydata.ot.ToString()));
@@ -150,7 +156,7 @@ namespace FPJ0000.JobReport_
{ {
rowdata.Add((daydata.hrs.ToString() + "+" + daydata.ot.ToString())); rowdata.Add((daydata.hrs.ToString() + "+" + daydata.ot.ToString()));
} }
} }
} }
else rowdata.Add("--"); //업무일지에 자료가 없다. else rowdata.Add("--"); //업무일지에 자료가 없다.
@@ -158,13 +164,13 @@ namespace FPJ0000.JobReport_
rowdata.Add(sum.ToString() + "+" + sumOT.ToString() + "(*" + sumFR.ToString() + ")"); rowdata.Add(sum.ToString() + "+" + sumOT.ToString() + "(*" + sumFR.ToString() + ")");
this.dataGridView1.Rows.Add(rowdata.ToArray()); this.dataGridView1.Rows.Add(rowdata.ToArray());
} }
foreach(DataGridViewRow dvrow in this.dataGridView1.Rows) foreach (DataGridViewRow dvrow in this.dataGridView1.Rows)
{ {
for(int i = 1;i < this.dataGridView1.ColumnCount-1;i++) for (int i = 1; i < this.dataGridView1.ColumnCount - 1; i++)
{ {
var col = this.dataGridView1.Columns[i ]; var col = this.dataGridView1.Columns[i];
var cellvalue = "--"; var cellvalue = "--";
if(dvrow.Cells[i].Value != null) cellvalue= dvrow.Cells[i].Value.ToString(); if (dvrow.Cells[i].Value != null) cellvalue = dvrow.Cells[i].Value.ToString();
if (cellvalue == "--") dvrow.Cells[i].Style.ForeColor = Color.Gray; if (cellvalue == "--") dvrow.Cells[i].Style.ForeColor = Color.Gray;
else if (cellvalue == "휴가") dvrow.Cells[i].Style.ForeColor = Color.Tomato; else if (cellvalue == "휴가") dvrow.Cells[i].Style.ForeColor = Color.Tomato;
else else
@@ -174,7 +180,7 @@ namespace FPJ0000.JobReport_
double ot; double ot;
if (double.TryParse(datasplbu[1], out ot) == false) ot = 0; if (double.TryParse(datasplbu[1], out ot) == false) ot = 0;
if(col.Tag.ToString() == "1") if (col.Tag.ToString() == "1")
{ {
dvrow.Cells[i].Style.ForeColor = Color.Green; dvrow.Cells[i].Style.ForeColor = Color.Green;
} }
@@ -198,10 +204,10 @@ namespace FPJ0000.JobReport_
dvrow.Cells[i].Style.ForeColor = Color.Red; dvrow.Cells[i].Style.ForeColor = Color.Red;
} }
} }
} }
} }
} }
this.dataGridView1.AutoResizeColumns(); this.dataGridView1.AutoResizeColumns();
} }
@@ -209,11 +215,11 @@ namespace FPJ0000.JobReport_
private void tbProcess_SelectedIndexChanged(object sender, EventArgs e) private void tbProcess_SelectedIndexChanged(object sender, EventArgs e)
{ {
} }
private void button1_Click_1(object sender, EventArgs e) private void button1_Click_1(object sender, EventArgs e)
{ {
} }
private void lbStt_Click(object sender, EventArgs e) private void lbStt_Click(object sender, EventArgs e)
@@ -249,7 +255,7 @@ namespace FPJ0000.JobReport_
var sdo = DateTime.Parse(this.tbMon.Text + "-01"); var sdo = DateTime.Parse(this.tbMon.Text + "-01");
var sd = sdo.AddMonths(-1); var sd = sdo.AddMonths(-1);
tbMon.Text = sd.ToString("yyyy-MM"); tbMon.Text = sd.ToString("yyyy-MM");
} }
private void toolStripButton7_Click(object sender, EventArgs e) private void toolStripButton7_Click(object sender, EventArgs e)

View File

@@ -1,4 +1,5 @@
using FCOMMON; using FCOMMON;
using AR;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
@@ -12,10 +13,11 @@ namespace FPJ0000.JobReport_
{ {
public partial class rJobReportOT : fBase public partial class rJobReportOT : fBase
{ {
int curLevel=0;
public rJobReportOT() public rJobReportOT()
{ {
InitializeComponent(); InitializeComponent();
//this.WindowState = FormWindowState.Maximized; curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.otconfirm));
} }
private void rJobReport_Load(object sender, EventArgs e) private void rJobReport_Load(object sender, EventArgs e)
@@ -38,14 +40,16 @@ namespace FPJ0000.JobReport_
cmbUserList.SelectedIndex = 0; cmbUserList.SelectedIndex = 0;
refrehData(); //refrehData();
} }
void refrehData() void refrehData()
{ {
////휴일데이터가 들어가 있음. if(curLevel < 5)
//var taH = new dsReportTableAdapters.HolidayLIstTableAdapter(); {
//taH.Fill(this.dsReport.HolidayLIst, tbMon.Text + "%"); UTIL.MsgE("사용 권한이 없습니다");
return;
}
var isReqData = cmbApploval.SelectedIndex > 0; //미승인선택 var isReqData = cmbApploval.SelectedIndex > 0; //미승인선택
string prcname = tbProcess.SelectedIndex < 1 ? "%" : tbProcess.Text.Trim(); string prcname = tbProcess.SelectedIndex < 1 ? "%" : tbProcess.Text.Trim();
@@ -459,7 +463,7 @@ namespace FPJ0000.JobReport_
private void tbProcess_SelectedIndexChanged(object sender, EventArgs e) private void tbProcess_SelectedIndexChanged(object sender, EventArgs e)
{ {
if (tbProcess.SelectedIndex >= 0) refrehData(); if (tbProcess.SelectedIndex >= 0 && curLevel >= 5) refrehData();
} }
private void button1_Click(object sender, EventArgs e) private void button1_Click(object sender, EventArgs e)

View File

@@ -38,6 +38,13 @@ namespace FPJ0000.JobReport_
//사용자 목록을 선택한다 //사용자 목록을 선택한다
UpdateUserList(); UpdateUserList();
var curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
if(curLevel < 5)
{
tbProcess.Enabled = false;
cmbUser.Enabled = false;
}
//this.tbMon.Text = DateTime.Now.ToString("yyyy-MM"); //this.tbMon.Text = DateTime.Now.ToString("yyyy-MM");
refrehData(); refrehData();
binit = true; binit = true;

View File

@@ -45,6 +45,13 @@ namespace FPJ0000.JobReport_
//사용자 목록을 선택한다 //사용자 목록을 선택한다
UpdateUserList(); UpdateUserList();
var curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
if(curLevel < 5)
{
tbProcess.Enabled = false;
cmbUser.Enabled = false;
}
refrehData(); refrehData();
binit = true; binit = true;
} }

View File

@@ -47,6 +47,12 @@ namespace FPJ0000.JobReport_
binit = true; binit = true;
tbProcess.SelectedIndexChanged += tbProcess_SelectedIndexChanged; tbProcess.SelectedIndexChanged += tbProcess_SelectedIndexChanged;
var curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.jobreport));
if(curLevel < 5)
{
tbProcess.Enabled = false;
cmbUser.Enabled = false;
}
} }
void UpdateUserList() void UpdateUserList()
{ {

View File

@@ -97,6 +97,8 @@
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ta = new FPJ0000.DSKuntaeTableAdapters.EETGW_HolydayRequestTableAdapter(); this.ta = new FPJ0000.DSKuntaeTableAdapters.EETGW_HolydayRequestTableAdapter();
this.cmbUser = new System.Windows.Forms.ToolStripComboBox();
this.toolStripLabel1 = new System.Windows.Forms.ToolStripLabel();
((System.ComponentModel.ISupportInitialize)(this.bn)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.bn)).BeginInit();
this.bn.SuspendLayout(); this.bn.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.bs)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.bs)).BeginInit();
@@ -317,6 +319,8 @@
this.dtED, this.dtED,
this.toolStripButton7, this.toolStripButton7,
this.toolStripSeparator2, this.toolStripSeparator2,
this.toolStripLabel1,
this.cmbUser,
this.btSearch, this.btSearch,
this.toolStripButton2, this.toolStripButton2,
this.toolStripSeparator3, this.toolStripSeparator3,
@@ -681,6 +685,18 @@
// //
this.ta.ClearBeforeFill = true; this.ta.ClearBeforeFill = true;
// //
// cmbUser
//
this.cmbUser.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbUser.Name = "cmbUser";
this.cmbUser.Size = new System.Drawing.Size(150, 37);
//
// toolStripLabel1
//
this.toolStripLabel1.Name = "toolStripLabel1";
this.toolStripLabel1.Size = new System.Drawing.Size(43, 34);
this.toolStripLabel1.Text = "담당자";
//
// fHolyRequest // fHolyRequest
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
@@ -771,5 +787,7 @@
private System.Windows.Forms.DataGridViewTextBoxColumn Response; private System.Windows.Forms.DataGridViewTextBoxColumn Response;
private System.Windows.Forms.DataGridViewTextBoxColumn HolyBackup; private System.Windows.Forms.DataGridViewTextBoxColumn HolyBackup;
private System.Windows.Forms.DataGridViewTextBoxColumn remarkDataGridViewTextBoxColumn; private System.Windows.Forms.DataGridViewTextBoxColumn remarkDataGridViewTextBoxColumn;
private System.Windows.Forms.ToolStripLabel toolStripLabel1;
private System.Windows.Forms.ToolStripComboBox cmbUser;
} }
} }

View File

@@ -36,6 +36,8 @@ namespace FPJ0000
cmbCf.DisplayMember = "DP"; cmbCf.DisplayMember = "DP";
cmbCf.ValueMember = "VAL"; cmbCf.ValueMember = "VAL";
dv1.EditMode = DataGridViewEditMode.EditProgrammatically; dv1.EditMode = DataGridViewEditMode.EditProgrammatically;
curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.holyreq));
} }
void __Closed(object sender, FormClosedEventArgs e) void __Closed(object sender, FormClosedEventArgs e)
@@ -48,19 +50,71 @@ namespace FPJ0000
private void __Load(object sender, EventArgs e) private void __Load(object sender, EventArgs e)
{ {
EnsureVisibleAndUsableSize(); EnsureVisibleAndUsableSize();
curLevel = Math.Max(FCOMMON.info.Login.level, FCOMMON.DBM.getAuth(FCOMMON.DBM.eAuthType.holyreq));
this.dtED.Text = DateTime.Now.AddMonths(1).ToShortDateString();// sdate.AddMonths(1).AddDays(-1).ToShortDateString(); this.dtED.Text = DateTime.Now.AddMonths(1).ToShortDateString();// sdate.AddMonths(1).AddDays(-1).ToShortDateString();
this.dtSD.Text = DateTime.Now.AddMonths(-1).ToShortDateString(); this.dtSD.Text = DateTime.Now.AddMonths(-1).ToShortDateString();
this.dv1.EditMode = DataGridViewEditMode.EditProgrammatically; this.dv1.EditMode = DataGridViewEditMode.EditProgrammatically;
UpdateUserList();
btSave.Visible = false;// curLevel >= 5; btSave.Visible = false;// curLevel >= 5;
btEdit.Text = curLevel >= 5 ? "승인(&E)" : "편집(&E)"; btEdit.Text = curLevel >= 5 ? "승인(&E)" : "편집(&E)";
// binit = true; // binit = true;
if (curLevel < 5)
{
cmbUser.Enabled = false;
}
else
{
if (cmbUser.Items.Count > 0)
cmbUser.SelectedIndex = 0;
}
refreshData(); refreshData();
} }
void UpdateUserList(bool datelist = false)
{ //this.cmbUser.DisplayMember = "dispName";
//this.cmbUser.ValueMember = "id";
// this.bs.DataSource = dr;
this.cmbUser.Items.Clear();
this.cmbUser.Items.Add("-- ALL --");
//해당그룹내의 사용자 목록을 가져와야한다
if (datelist == false)
{
var dtUser = FCOMMON.DBM.getActiveUserTable();
foreach (DataRow dr in dtUser.Rows)
{
this.cmbUser.Items.Add(dr["dispname"].ToString());
}
}
else
{
var ta = new dsQueryTableAdapters.HolydayUserListTableAdapter();
var dtUser = ta.GetData(FCOMMON.info.Login.gcode, dtSD.Text, dtED.Text);
foreach (dsQuery.HolydayUserListRow dr in dtUser.Rows)
{
this.cmbUser.Items.Add($"{dr.UserName}({dr.uid})");
}
}
this.cmbUser.Text = $"{FCOMMON.info.Login.nameK}({FCOMMON.info.Login.no})";
//if (this.cmbUser.SelectedIndex < 0) this.cmbUser.SelectedIndex = 0;
}
string GetUIDValue()
{
string uid = "%";
if (cmbUser.SelectedIndex > 0)
{
var si = cmbUser.Text.IndexOf("(");
var ei = cmbUser.Text.LastIndexOf(")");
uid = cmbUser.Text.Substring(si + 1, ei - si - 1);
}
return uid;
}
private bool getKisulInput private bool getKisulInput
{ {
@@ -112,7 +166,13 @@ namespace FPJ0000
//dsMSSQL.JobReport.Clear(); //dsMSSQL.JobReport.Clear();
var sd = dtSD.Text.Trim(); var sd = dtSD.Text.Trim();
var ed = dtED.Text.Trim(); var ed = dtED.Text.Trim();
ta.Fill(this.dSKuntae.EETGW_HolydayRequest, FCOMMON.info.Login.gcode, sd, ed); var seluid = GetUIDValue();
var uid = "";
if (cmbUser.SelectedIndex == 0) uid = "%";
else uid = GetUIDValue();
ta.Fill(this.dSKuntae.EETGW_HolydayRequest, FCOMMON.info.Login.gcode, sd, ed, uid);
var sum_day = dSKuntae.EETGW_HolydayRequest.AsEnumerable().Where(t => t.conf == 1).Sum(t => t.HolyDays); var sum_day = dSKuntae.EETGW_HolydayRequest.AsEnumerable().Where(t => t.conf == 1).Sum(t => t.HolyDays);
var sum_time = dSKuntae.EETGW_HolydayRequest.AsEnumerable().Where(t => t.conf == 1).Sum(t => t.HolyTimes); var sum_time = dSKuntae.EETGW_HolydayRequest.AsEnumerable().Where(t => t.conf == 1).Sum(t => t.HolyTimes);
@@ -174,7 +234,7 @@ namespace FPJ0000
else else
{ {
search = search.Replace("'", "''"); search = search.Replace("'", "''");
var collist = new string[] {"name", "Response", "HolyReason","remark" }; var collist = new string[] { "name", "Response", "HolyReason", "remark" };
string filter = ""; // "itemna like ? or package like ? or projectname like ? or process like ? or [type] like ? or description like ?"; string filter = ""; // "itemna like ? or package like ? or projectname like ? or process like ? or [type] like ? or description like ?";
foreach (var col in collist) foreach (var col in collist)
{ {
@@ -334,11 +394,11 @@ namespace FPJ0000
} }
} }
if(FCOMMON.DBM.GetMagamStatus(dr.sdate.Substring(0,7))) if (FCOMMON.DBM.GetMagamStatus(dr.sdate.Substring(0, 7)))
{ {
FCOMMON.Util.MsgE("마감된 자료이므로 삭제할 수 없습니다"); FCOMMON.Util.MsgE("마감된 자료이므로 삭제할 수 없습니다");
return; return;
} }
if (FCOMMON.DBM.GetMagamStatus(dr.edate.Substring(0, 7))) if (FCOMMON.DBM.GetMagamStatus(dr.edate.Substring(0, 7)))
{ {
@@ -381,18 +441,18 @@ namespace FPJ0000
var drv = this.bs.Current as DataRowView; var drv = this.bs.Current as DataRowView;
if (drv == null) return; if (drv == null) return;
var dr = drv.Row as DSKuntae.EETGW_HolydayRequestRow; var dr = drv.Row as DSKuntae.EETGW_HolydayRequestRow;
if(dr.cate.Equals("외출")==false) if (dr.cate.Equals("외출") == false)
{ {
FCOMMON.Util.MsgE("외출 자료만 완료할 수 있습니다"); FCOMMON.Util.MsgE("외출 자료만 완료할 수 있습니다");
return; return;
} }
if(dr.conf != 1) if (dr.conf != 1)
{ {
FCOMMON.Util.MsgE("관리자 승인된 자료만 완료할 수 있습니다"); FCOMMON.Util.MsgE("관리자 승인된 자료만 완료할 수 있습니다");
return; return;
} }
var f = new OtConfirm.fOutCoomplete(dr); var f = new OtConfirm.fOutCoomplete(dr);
if(f.ShowDialog() == DialogResult.OK) if (f.ShowDialog() == DialogResult.OK)
{ {
dr.stime = f.dtSD.Value.ToString("HH:mm"); dr.stime = f.dtSD.Value.ToString("HH:mm");
dr.etime = f.dtED.Value.ToString("HH:mm"); dr.etime = f.dtED.Value.ToString("HH:mm");

View File

@@ -130,78 +130,78 @@
<data name="bindingNavigatorMoveFirstItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="bindingNavigatorMoveFirstItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wQAADsEBuJFr7QAAASpJREFUOE9jGDygcNbz/00Lnv/PnPj4P1QIA4S3P8Apx5A789n/VUfe/8elKL77 wQAADsEBuJFr7QAAATFJREFUOE9jYBg0oHDW8/9NC57/z5z4+D+6HAyEtz/AKceQO/PZ/1VH3v/HpSi+
wf/ghmu4DciY8vT/wn0fsCqK73n4f+n+///9qy/gNiCh58n/aVveYyiKaL8P1pw56/9/r9ITuA2I7Hr0 +8H/4IZrWOXAIGPK0/8L933Aqii+5+H/pfv///evvoAhBwcJPU/+T9vyHkNRRPt9sObMWf//e5WewG1A
v3f1BxRFoa33wJpb1wFt7/z73yX/AG4DApsf/q+b/w6uKLjl7v9Fe///7wBqzpjz879d3c//9hnbcRvg ZNej/72rP6AoCm29B9bcuu7/f//Ov/9d8g/gNiCw+eH/uvnv4IqCW+7+X7T3//+Odf//Z8z5+d+u7ud/
UXX/f/60NyiK7Ipv/0+f8/u/f9e3/zqF7/5bJKzHbYB96d3/2ZNfYyjSTzn/36ToxX+VrE//jSOX4TbA +4ztuA3wqLr/P3/aGxRFdsW3/6fP+f3fv+vbf53Cd/8tEtbjNsC+9O7/7MmvMRTpp5z/b1L04r9K1qf/
Iu/O/9T+11gVGSSd+C+b9vW/bvA83AYYZt3+H9byEqci/dTL/zV8p+E2QCftxn+/6od4Fal4TMBtgFPu xpHLcBtgkXfnf2r/a6yKDJJO/JdN+/pfN3gehhwcGGbd/h/W8hKnIv3Uy/81fKdhlQMDnbQb//2qH+JV
lf8gBXgVDULAwAAA8HbAq6XlmnAAAAAASUVORK5CYII= pOIxAaccg1Pulf8gBXgVDUoAAPB2wKtYlLYeAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="bindingNavigatorMovePreviousItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="bindingNavigatorMovePreviousItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wQAADsEBuJFr7QAAALZJREFUOE9jGDogvP3BfyiTdBDf/eB/cMM18gyI73n4f+n+///9qy+QbkBE+32w wQAADsEBuJFr7QAAALtJREFUOE9jYBgyILz9wX90MaJBfPeD/8EN18gzIL7n4f+l+///96++QLoBEe33
5sxZ//97lZ4gzYDQ1ntgza3rgLZ3/v3vkn+AeAOCW+7+X7T3//8OoOaMOT//29X9/G+fsZ00F9gV3/6f wZozZ/3/71V6gjQDQlvvgTW3rvv/37/z73+X/APEGxDccvf/or3//3es+/8/Y87P/3Z1P//bZ2wn3gAQ
Puf3f/+ub/91Ct/9t0hYT3oY6Kec/29S9OK/Stan/8aRy0g3AAQMkk78l037+l83eB55BoCAfurl/xq+ sCu+/T99zu///l3f/usUvvtvkbCeNANAQD/l/H+Tohf/VbI+/TeOXEa6ASBgkHTiv2za1/+6wfPIMwAE
08g3AARUPCZQZsBgBQwMANAUYJgEulBVAAAAAElFTkSuQmCC 9FMv/9fwnUa+ASCg4jGBMgMGLwAA0BRgmCws/7cAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="bindingNavigatorMoveNextItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="bindingNavigatorMoveNextItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wQAADsEBuJFr7QAAAKNJREFUOE9jGHygcNbz/1AmeSB35rP/Cd33yDckY8rT//P2//6f0HWHPEMSep78 wQAADsEBuJFr7QAAAKRJREFUOE9jYBh0oHDW8//oYiSB3JnP/id03yPfkIwpT//P2//7f0LXHfIMSeh5
n73v1//OrX//u5VeJt2QyK5H/6ds+/W/ZOnf/wnT//63yT1LmiGBzQ//t659D9ZsXPLlv3T0tf/GkcuI 8n/2vl//O7f+/e9Wepl0QyK7Hv2fsu3X/5Klf/8nTP/73yb3LGmGBDY//N+69j1Ys3HJl//S0df+G0cu
N8Sj6v7/krnv4JoVXXpIc4F96d3/gS3PyNMMAhZ5d/7bFFwhTzMIGGbdJl8zCOik3SBf81AEDAwAoH5f I94Qj6r7/0vmvoNrVnTpIV4zCNiX3v0f2PKMPM0gYJF3579NwRXyNIOAYdZt8jWDgE7aDfI1D00AAKB+
oAc0QjgAAAAASUVORK5CYII= X6Bjq5qXAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="bindingNavigatorMoveLastItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="bindingNavigatorMoveLastItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
wQAADsEBuJFr7QAAASxJREFUOE9jGFygcNbz/1AmBgDJNS14/j9z4mOcahhyZz77n9B9D6sCkNyqI+// wQAADsEBuJFr7QAAAStJREFUOE9jYBhUoHDW8//oYjAAkmta8Px/5sTHONUw5M589j+h+x5WBSC5VUfe
h7c/wG1AxpSn/+ft//0/oesOhiKQ3MJ9H/4HN1zDbUBCz5P/s/f9+t+59e9/t9LLKApBctO2vP/vX30B /w9vf4BVHgwypjz9P2//7/8JXXcwFIHkFu778D+44RqGHBwk9Dz5P3vfr/+dW//+dyu9jKIQJDdty/v/
twGRXY/+T9n263/J0r//E6b//W+TexauGCTXu/rDf6/SE7gNCGx++L917XuwZuOSL/+lo6/9N45cBtYA /tUXcBsQ2fXo/5Rtv/6XLP37P2H63/82uWfhikFyvas//PcqPYHbgMDmh/9b174HazYu+fJfOvraf+PI
kqub/+6/S/4B3AZ4VN3/XzL3HVyzoksPXDFILn/am//2GdtxG2Bfevd/YMszDM0gAJLLnvz6v0XCetwG ZWANILm6+e/+u+QfwG2AR9X9/yVz38E1K7r0wBWD5PKnvflvn7EdtwH2pXf/B7Y8w9AMk8ue/Pq/RcJ6
WOTd+W9TcAVDMwiA5FL7X8O9hBUYZt3GqhkEQHJhLS//6wbPw22ATtoNnJIgOb/qh/81fKfhNgAfcMq9 3AZY5N35b1NwBUMzTC61/zXcS1iBYdZtrJpBACQX1vLyv27wPKzyYKCTdgOnJEjOr/rhfw3faTjV4AVO
8l/FYwIYQ4UGBWBgAAC+0b+zuQxOnAAAAABJRU5ErkJggg== uVf+q3hMAGN0uYEFAL7Rv7NmXVYYAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="btFind.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="btFind.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE3SURBVDhPnZIxS8NQFEb7W/wLjh0Fl9a1SxBHBekkWFd1 YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEwSURBVDhPpZIxSwNBEIXzW/wLKS0Fm2ib5hBLBbESjG20
qYg4Ci5dndSCg2AHl4LQSaRSKDqoFUE7VAjUmvTKueWmL2mw2gunL7zmO+/mJhmZoTJusdF868vpXUfO UUQsBRtbKzVgIWhhIwhWIhFBtFAjgqaIcKDmLiPfwO7NXg6NZuDdLnv3vn03uyX5R5VssdB8+ZC9q5Yc
b5/lpPEox9f3SvnsRtk8uojxHQ7HEgSEkXS6vrz3xqtdu+xdfUiheEBsJOGCk/mz/hROUHsIIrp+qIKY XD7K7sW9bJ9eq1b3z1WLW4eBumkvgwDADKTVjuW1k41ubrV2/CbV+Y0sCRN25uXZQ9qnk7vEqx2nCggg
hB/a9r+CVAG4Auj5g7iA5/1NACaptgIVLHkb0wWVw13ZL60p2+uerqkCJs1mMgwUU6d1k/xJwI10RZj1 PIgdfyZ95jwEAOrEXyGA//0JYCGNm0QBk9HC74CdzRVZr82q6nORjoUAOs1i3owouk50BxkIwIekwsz4
9TPUN7Wam9dgTMC75QR7TjCBkRQs5Jd1jQS8c1ewtZLTPcQW/peADpC44cudgnjZOQ1OCGjTwkwaGBon /J7qSc1UymoMAJwtO9iOO4BTHjA2MRUCOHMLWJqu6BpgZ/4TgARArPlouSrR6EgxgJj2qBBNY0cnzI3a
GoSrpcVIQqmAj6LZftFBup9vWiUlUQdIDCbsQrsGZRJKBbOXyA++SlEsu6QjvQAAAABJRU5ErkJggg== uId4AJeiefukjbTXt6jyEJ8AiBMdtiKuk4V4wDD1Db5KUSxr13uqAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="btSave.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="btSave.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE1SURBVDhPY/hPIQAbcOn57//T915BwW1rjoFx/oJz//N6 YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEzSURBVDhPY/hPIWAAEZee//4/fe8VFNy25hgY5y849z+v
VqHgsNxeMA03YN3lp/9vv4YYhAtsuQ6h55/9A8aBidVgPtiADZcegzWDFN1/9///qy8IDOKDcPfu1/9/ ZxUKDsvtBdNwA9Zdfvr/9muIQbjAlusQev7ZP2AcmFgN5oMN2HDpMVgzSNH9d///v/qCwCA+CHfvfv3/
/vn/v3rt/f9TD38BuwJuwIrT9wka0L79BdiAkuW3MA0A+fnog///V12GKAZ5BxcGGQByDYoXYAbA/Aey 55///6vX3v8/9fAXsCvgBqw4fZ+gAe3bX4ANKFl+C9MAkJ+PPvj/f9VliGKQd3BhkAEg16B4AWYAzH8g
AYRBCkE2N256AnY6SDMoUEF8FANAoQ0zAFkzCCNrhhkAor3CczENwGYzuu1JM8+BaQwDQAGITzOyASDs G0AYpBBkc+OmJ2CngzSDAhXERzEAFNowA5A1gzCyZpgBINorPBfTAGw2o9ueNPMcmMYwABSA+DQjGwDC
4huPMAAkATIA3c/YNIdNPAHGKAaAUhUoBghphhng0rTnv71bGKoBoADE5mR0zVgNACUK9BgAGYbudJBG Lr7xCANAEiAD0P2MTXPYxBNgjGIAKFWBYoCQZpgBLk17/tu7haEaAApAbE5G14zVAFCiQI8BkGHoTgdp
GNY0dEYYAMsgMAyKYxAGhTQIg/wLwiBbQRikGSUdkA/+/wcAgXJEf04PwQkAAAAASUVORK5CYII= hGFNQ2dUF4AMgWFQHIMwKKRBGORfEAbZCsIgzSjpgBIAAIFyRH86fUztAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<data name="toolStripButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="toolStripButton1.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIFSURBVDhPpZLtS1NhGMbPPxJmmlYSgqHiKzGU1EDxg4iK
YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9 YKyG2WBogqMYJQOtCEVRFBGdTBCJfRnkS4VaaWNT5sqx1BUxRXxDHYxAJLvkusEeBaPAB+5z4Jzn+t3X
0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw /aLhnEfjo8m+dCoa+7/C3O2Hqe0zDC+8KG+cRZHZhdzaaWTVTCLDMIY0vfM04Nfh77/G/sEhwpEDbO3t
bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc I7TxE8urEVy99fT/AL5gWDLrTB/hnF4XsW0khCu5ln8DmJliT2AXrcNBsU1gj/MH4nMeKwBrPktM28xM
VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9 cX79DFKrHHD5d9D26hvicx4pABt2lpg10zYzU0zr7+e3xXGcrkEB2O2TNec9nJFwB3alZn5jZorfeDZh
c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32 6Q3g8s06BeCoKF4MRURoH1+BY2oNCbeb0TIclIYxOhzf8frTOuo7FxCbbVIAzpni0iceEc8vhzEwGkJD
Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo lx83ymxifejdKjRNk/8PWnyIyTQqAJek0jqHwfEVscu31baIu8+90sTE4nY025dQ2/5FIPpnXlzKuK8A
mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+ HBUzHot52djqQ6HZhfR7IwK4mKpHtvEDMqvfCiQ6zaAAXM8x94aIWTNrLLG4kVUzgaTSPlzLtyJOZxbb
kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D 1wtfyg4Q+AfA3aZlButjSfxGcUJBk4g5tuP3haQKRKXcUQDOmbvNTpPOJeFFjordZmbWTNvMTHFUcpUC
TgDQASA1MVpwzwAAAABJRU5ErkJggg== nOccAdABIDXXE1nzAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
@@ -210,62 +210,62 @@
<data name="toolStripButton8.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="toolStripButton8.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAANPSURBVFhH7dhZTxNRHAVwPoRx3yuyKWUvqyJu4BqNiYnx YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAANNSURBVFhH7dhnT1NRHAZwPoRx74osZZTRUkARFzijMTEx
C/giaowRQSiibC0Uyg6CyqKSuEaEQvdCK7tPqAmokWDUiFGgyCrHO+k0oT609w4JvvQk9/n+MjPn/ifX fgHfiBpjRBCKIKuFQtkgoEBVElwRoaWTLkahvkJNQI0Eg0aMsqc85ia24TYBzrkk+KbPJ/jl3Puc/8nf
wx133BGQh8dfX3hwzGy9f7QfDUfIOtyH+kN9qEvoRW18L+4d7MHdAz24s5+sfd2o2duN6rgu3N7TharY w8Mdd9yhz9Ozb689OWMZf3zaDsUpOxQne1B/ogd1cd2oje3Go+M2PDxmQ81RG2qOdKH6cBeqYjrx4FAn
TlTu7kTFrlcojyEr2oKyKAtKIy0oiTCjONyMIkkHlGFkhbajMKQdBcEma36QIZHf3nWWGQdFkAm5gaYJ KqM7UHGwA+UH2lEW1Y6ySCtKI6woEVlRHG5BkdCCQoEZ8jAz5KEmFISYkB9sHM/jG+JdHUtmjXGQ8Y3I
fnvXWW5cfqAJeQFG8Nu7zv/AycUswCXgyqLNUEbokSdpQ4FEh6LwDiqc3N9AD1zKkyuM1KL/8UfMTs2j CTKOuTqWzFrj8oKMyA1sg6tjyfwPnDSABrgKXGmkBfJwPXIFrcgX6FAoNBPhpP4GciBXHHNyBSIt7M8+
p/ED5CEaKpxsJwNQKI57cu2V77A4xfFaKlzuDj09UAiuONKER5e6sfBngacBP0cmIQtTUeFy/BiArLjS Y3ZqHraGT5CGaIhwkv0UQK445uRMFR+wOEWxWiJczj49OZALrkhkROONLiz8WXDifg1OQBKmJMJl+1EA
qA5UnTJgemKWpwFzM/OoOWuEIthIhcv21dED2XCkFLFafH8/ztNseSHtR16wjhqX5cMApMVxR4kiXIO3 aXElEWZUXjBgemzWiZubmUf15TbIgtuIcFm+OnIgHc4CebQWPz6OOnFMXovtyA3WEeMyfSiApDjmKpEJ
ms88y5auhiFy8KqZcJneLEBKXGG4HqYKx1IM94+S766VGZfppaUH0uCKIkgpLjqWYuzLbxTGqcl3Z2DG NXiv+crCdSr6kROkpsJleNMACXEFQj2M5exSDNiHIQlTUeMyvLTkQBJcYbgRjdfZpRgZmkRBjBqyYAM1
3drOAHSFK4nkS2Gd42m2UlSfMYIMfUG4m54aeqAzHDe+FGE6DHV85Wm2PEvpgzxIKxiXsY0B6AzHzdb8 7v5eCuBKuGLRv1KMzzlxTCmqLrUhj88Nl+6pIQcuh2PGlyxMh37zNyeOycukHkj5Ws64tD0UwOVwzGzN
UB0G2x2BT5N7IQvUCsbdEKnpgc5w3OBXSkwoP6F3fMXT86g8TUBivSBc+lYGoDOcffArQvRoTOxyKMkv C9Whz8QGvkjshiRIyxl3j6cmBy6HYwa/XGBE2Tk9+xNPz6PiogGSAD0nXOpuCuByOMfgl4Xo0RDfySrJ
UhJ5TCtk/jpmnHRLGz3QFc4+W2VBGuhL3/A8Wz71jSJT3MyMS9vMAqTA2c+5LLEKA20jPM8WS+0gMnxb 76FJSKNUkPjrqHHiXa3kwJVwjtkq4WugL3nnBDL50jOMjIBmalzKThogAc5xz2UGKNHbOshCWmv7kObb
mHBpm1rpgbQ4rhDyAANyJCp8GxrjebY8SepBhncrNS51IwOQFmdvK/fNKRM0mBpf9LNASlN6kqC81FS4 QoVL2aEiB5LimEJIAw3IFijxvX+EhXyeYEOat4oYl7ydAkiKc7SV+efkcRpMjS56LEzPo+S8FuleaiLc
6xsYgCw4e1uz/NSoP2d2KM2P4QlIfZqocCnrVfRAVpy9EBk+KmiUAzzPluyIFipc8joGoBCcvRBS75fo 3W0UQBqco62ZfmrUX7GwSvNzYAxinyYiXNJWJTmQFucoRJqPEhp5rxPIJCu8hQiXuIUCyAXnKITY+w06
JH8zM5NzsNQNIlXURIW7traFHigUZy+E1LMFKaLnBNeMdFEbFS5pDQtwCTjaQvyLS1rdTA/8H7irqxiA FP2YmZiDta4PybwmItydzS3kQK44RyHEni1I4r1CMq8ZqbxWIlzCJhrgKnCkhXDFJWxsJgf+D9ztDRRA
BGddbtzllU30Vx/cRQ53V7KcuCsrms7z27vjjjv08fD4CwlIPe+HvHrCAAAAAElFTkSuQmCC Zley1rib65vIVx/MIofZlawl7ta6pquuDnfccYcgfwEJSD3vAJhh2AAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="toolStripButton7.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="toolStripButton7.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAANSSURBVFhH7djZTxNRGAVw/gjjvq9tVWgBAbUguO+aGE18 YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAANRSURBVFhH7dhZT5NBGAVgfoRx31daWVpAUCgI7uCaGE28
8N0XFROj4oYitHbB0haL4i4qGhUTRew27bS1pRSEJ4kkKCZuiRhJpEQE5TjDTKPEpL13TPClJ7nP95e5 8N4bFROjgqKApaVspQXZXZBNo2LiAm3pR7+2tpSW5UqCCQKJookYSaRGFOGYIWm1GGDmM4Gbnl/wZCZn
c+a7mZRkkklGQu5saSus3RyM3t7UilsbubXhOW6uf46adS24sbYF19c049rqZlxdxa2VEVxZEcHl5U24 3skbEOCPP/6w58HR7uSGIzZ3/eEu1B3qQt3BTtQmdaImsQP3D3Sger8L9/a5cHevC3f3OHFntxO3d7Wj
VNCEi/lhVC8L40JeI87ncksdQtXSEGxLQji3OIjKnCCs2c9gyeLWogDMmQFUZPijZ9PZfeL2iTPKOJjS KqEdlfEOVOx0oDyuDWWxbSiT2VEaY0dJtB23dthQvN2GoqhX0Ea+gnabFZoIKwrDLe6CMP78dMeMmWcc
/dCr/L3i9okz2rizKj/KlT6I2yfO/8AZ02iAhLiLBWHY8nwwq12oVLOoyg1JxhlTWXIg6ZOrzGXRer8L 1GEW5Egto9MdM2a+cQVSC/IlZkx3zJiFwOWFsgApcZUJDpTEmaGRtaBYxqM01i4YlxfC0wNpcOTkimN5
A99+oK3uDSxLGck4w0IKIPGxbmXxZwLVL2HO8UrC6Rd4yYGk75w1n0HP+z6RBwz9HMK9/RGYs33UON18 dD0ewM/vv9DdOAhtDCcYlxvMAKTBTV3rMR5/x1rRC812kyBcTpCJHkiF2+lAUTyHkaFvXuDkxCQeXXBC
CiBpIWzqIK7vCgwfcSzfo4Oo3s7CnOWnwp1ReMiBJLhYW61LfHh0vFXkCfn8phemPCcqMv3EOK2cAkiK E2Vmxqm2MgBpcKQQJTIbqk9bp67Ykx/ucVSc4KGJtDDhssWt9EAanKetRdFmPEvr8gJJPg+OQh1nQGGE
ixXClOVBpPaVyBPSwX6EPt1BjNPIaIAUuFghjNkOdEW6RZ4Qr60dOqWbCKeZx5ADaXF8IcxZ3LuW70TP hRqnFDEAaXGeQqgjW+FseOuDfMN/RE6YnhqnCGQBMuA8hciL0mPAOeyDNJX0QCUxUuEUWzh6ICuOFEIT
uz9KMwTcLQzjTKo7Ia5sLgWQFhdrqynDh0s7WQz2/y5Nf+8ArBvc0C/0xMWVznGTA6XgYm01qBg8PNIi aUVhvAEj7/8qzSTwMNmB7BDjnLiszQxAVpynrepwM6pO8Rgf+1OasdGfKDpoRE5w66w4+SYjPVAIztPW
8oR0+D6iVGGPizs9mwIoFccXQq9kUFc0EvjS+4EDOuLiSma5yIFScUYliws7vH8dsXmdC1oFExd3aiYF XCmHp6kdXiDJG/NHyMW6WXE3NzIAheKmfiUSDo0pvsBe0wfIxfpZcZkbWuiBQnF5Eh7lJ03/XLEmsQVK
UAquXOWDQW3Hl7dRkSaUpHZPI0rljoS4kzOc5EBaHP+d0ygb8DrySaQJYSwvcFpuJ8IVT6cBUuK0qU40 MTcrLmM9A1AILl9qRq5Mhy/v3F4cKUnD2TbIRfo5cenrDPRAVhx55xSSJvQ7P3lxJJz2NW6KdFS4G2tZ
3uwUWULamfcoUTwhxhVPc5ADaXC6NDceHGoWWUK6X3+FJrMBGjlDjDsxlQJIijOkeVG1zTvistDPXRYs gIw4ZYgBbbV9PrgebgiZ4pfUuBtr9PRAFpwq1Ignl10+uOH+r1BENEEh4qhx11czAGlxuaEmlB43+XwW
613UuONTKIAkOH58aVVPR5aCu27V7A6iVOakxh2bbCcHkuD42WoqcIo0IXwpSmR2SbijkyiAJDh+tpbN xtzj0Ca1MOPSVjEAaXBkfCmlzb6lmJhEzRkb5IEGZty1lTp6IA2OzFZ1gsGLIyGlyAzUCcJdXcEApMGR
t6Ppdie+9w0ifKsTp+RPJOOOTHxKDiTB8YNft8AzPCFOyh7/05PjcUUTaIAEuESDnxZXNL6BHPg/cIfH 2Zq1VYf2+j78+DYOR10fMkQvBeNSlzfTA2lwZPCrglqnJkR64PP/OjmCS1nGAqTAzTX4WXEpS5vogQuB
UQA5XHS0cQfG1pP/+uB/5PD/SkYTd3BM/V5x+2SSSYY8KSm/AHvBPpKbf2MsAAAAAElFTkSuQmCC u7KEAUh2JfONu7j4Bf3qgyxyyK5kPnGXFr04N93hjz/+UOQ3e8E+krxr0cIAAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="btSearch.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="btSearch.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAE4SURBVDhPtZPPasJAEMbzPn0FwWA92JtP4NGKB1/DP7ei YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEiSURBVDhPY2DAAf6jAXRxVNVIAKYga5bH/7TpTmAMYsNA
QSsovkChh7ZBrCfpyR4sikopUgq9StFzM/UbZ5asSS4FfzAkO7vft5udiZMEnSBpk5dhFJmncjdHxXaG 3EQb3Ab8+/fv/71PZ/5nzXX+f+3T7v+X320H0yCct8Dz/9rTM/8HtGvDDcPQDAIgBSCNOx9NBuOOiw7/
A+9K4SbFT1luEwQBbXavVO5d0nI3ovnW5yeiMriiu+kt5asXbABEdgRigAUQDr+aHLU3lxoLl/yPJhvF u644/N9+ZzLYIKwGwARAkvP2dIJpGN52Y/r/9gsO/zuu2P/f+3Qq3ACQhVhtz5jlBLcBJnb43Qyw5p0P
GsiYJ/vPdX5qPK3bVJ25VFukafztGQNsKHJ791I3w+8KcpNth8XDz5YxACI/gsR1J8sTYcO4UIzwv1gG pmB3AcwV6TNcwBLIBmLDKAbAeWQAFAPQbUG2DeYimAsxnA4z4PLnDWD/Hv2AGl0gAAobZAOxGgDSCApt
cTshgJ5IT8hChTMHsHi+v+fvffmxywVwN2FDkdsGEOK2ceu4feQ0tDqKyKMGqDfqjvprLzyswuX7Tf4E UKiDQh/ZJbDYgQGcBoDiGxTvoPiHpYUt15Gj7y9uL4BSGijFbb81FYy33pgK1gxKyqAUiuJ0ZAAyAJbG
dBo6zn/3OB7XHovRyuhQ6+hhYKA9DpL+A1keRebNAhkaJH0OHOcP031C4EjYr6wAAAAASUVORK5CYII= QQBXPkDXBwfoCuA60MRpAgDTfULg/+7qPQAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="toolStripButton2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="toolStripButton2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADlSURBVEhL7dQxCsIwFMbxnMrZWatzUXRUCo5ewSs4ewZR YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADiSURBVEhL7dVBCsIwEAXQnsq1a62ui6JLpeDSK3gF155B
DyDeQfEETsUbRL7YYNSXNC/UOiQP/kvzyE9KUcQ7y/VJtlHFvQYPjzf50xKsJsFmq81WHq538swMO9il 1AOId1A8gSvxBiNTCcTJJM3E2i6SwN9MhnklDW2WRbvW2wu0EepW8PkBf02CE2xks9vD6f4y6jTYg720
zhALxkWd7kAOJwsnjjPsYNeGs2B14fR5YTYq5O5c1u7sL987iAUjF+6LIjaMKJyDoiAYmVAvn8lsXHij riKCcVCvP4LxbOXEcQ97sNeGi+Bq4PwzMJ+UcLg+a3uON7NHDHODdZzu2dAgmAMQpzUXGgxTfFAsIJ+W
KBhGwDWof4APihqHqQ+OKhg2X3U/n7+9ah88CKY+pM9ndTgbplDbmQtnwS7UtmPDWfDf/jIRLnKhOuzY 3uhPMAZxBaoH8EExjcPcheMSDOtHPSyWX0ftgwfB3EWitTpcDFNAf6d0z4WLYDqYu0i0x4aL4M4+mZhO
UMSGmyrBauKE26jiohshHicE2B3dbRrmAAAAAElFTkSuQmCC fhJNJsERw22EuvGsNycE2B33w41tAAAAAElFTkSuQmCC
</value> </value>
</data> </data>
<metadata name="HolyDays.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> <metadata name="HolyDays.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">

View File

@@ -96,7 +96,12 @@ namespace FPJ0000
} }
if (curLevel < 5) if (curLevel < 5)
{
toolStripButton4.Enabled = false;
cmbUser.Enabled = false; cmbUser.Enabled = false;
tbProcess.Enabled = false;
}
//var userList = FCOMMON.DBM.getGroupList("name + '(' + id + ')'", "Users", "[level] > 0 and [level] < 10", false, false); //var userList = FCOMMON.DBM.getGroupList("name + '(' + id + ')'", "Users", "[level] > 0 and [level] < 10", false, false);

File diff suppressed because it is too large Load Diff

View File

@@ -33,6 +33,31 @@ ORDER BY projectName</CommandText>
</Mappings> </Mappings>
<Sources /> <Sources />
</TableAdapter> </TableAdapter>
<TableAdapter BaseClass="System.ComponentModel.Component" DataAccessorModifier="AutoLayout, AnsiClass, Class, Public" DataAccessorName="HolydayUserListTableAdapter" GeneratorDataComponentClassName="HolydayUserListTableAdapter" Name="HolydayUserList" UserDataComponentName="HolydayUserListTableAdapter">
<MainSource>
<DbSource ConnectionRef="gwcs (Settings)" DbObjectName="EE.dbo.Holyday" DbObjectType="Table" FillMethodModifier="Public" FillMethodName="Fill" GenerateMethods="Both" GenerateShortCommands="false" GeneratorGetMethodName="GetData" GeneratorSourceName="Fill" GetMethodModifier="Public" GetMethodName="GetData" QueryType="Rowset" ScalarCallRetval="System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" UseOptimisticConcurrency="true" UserGetMethodName="GetData" UserSourceName="Fill">
<SelectCommand>
<DbCommand CommandType="Text" ModifiedByUser="true">
<CommandText>SELECT uid, dbo.getUserName(uid) AS UserName
FROM Holyday WITH (NOLOCK)
WHERE (gcode = @gcode) AND (sdate &gt;= @sd) AND (sdate &lt;= @ed)
GROUP BY uid
ORDER BY UserName</CommandText>
<Parameters>
<Parameter AllowDbNull="false" AutogeneratedName="gcode" ColumnName="gcode" DataSourceName="EE.dbo.Holyday" DataTypeServer="varchar(10)" DbType="AnsiString" Direction="Input" ParameterName="@gcode" Precision="0" ProviderType="VarChar" Scale="0" Size="10" SourceColumn="gcode" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="sd" ColumnName="sdate" DataSourceName="EE.dbo.Holyday" DataTypeServer="date" DbType="AnsiString" Direction="Input" ParameterName="@sd" Precision="0" ProviderType="Date" Scale="0" Size="3" SourceColumn="sdate" SourceColumnNullMapping="false" SourceVersion="Current" />
<Parameter AllowDbNull="true" AutogeneratedName="ed" ColumnName="sdate" DataSourceName="EE.dbo.Holyday" DataTypeServer="date" DbType="AnsiString" Direction="Input" ParameterName="@ed" Precision="0" ProviderType="Date" Scale="0" Size="3" SourceColumn="sdate" SourceColumnNullMapping="false" SourceVersion="Current" />
</Parameters>
</DbCommand>
</SelectCommand>
</DbSource>
</MainSource>
<Mappings>
<Mapping SourceColumn="uid" DataSetColumn="uid" />
<Mapping SourceColumn="UserName" DataSetColumn="UserName" />
</Mappings>
<Sources />
</TableAdapter>
</Tables> </Tables>
<Sources> <Sources>
<DbSource ConnectionRef="gwcs (Settings)" DbObjectType="Unknown" GenerateShortCommands="true" GeneratorSourceName="CheckHoliday" MethodsParameterType="CLR" Modifier="Public" Name="CheckHoliday" QueryType="Scalar" ScalarCallRetval="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" UseOptimisticConcurrency="true" UserGetMethodName="GetDataBy" UserSourceName="CheckHoliday"> <DbSource ConnectionRef="gwcs (Settings)" DbObjectType="Unknown" GenerateShortCommands="true" GeneratorSourceName="CheckHoliday" MethodsParameterType="CLR" Modifier="Public" Name="CheckHoliday" QueryType="Scalar" ScalarCallRetval="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" UseOptimisticConcurrency="true" UserGetMethodName="GetDataBy" UserSourceName="CheckHoliday">
@@ -51,21 +76,21 @@ WHERE (pdate = @pdate)</CommandText>
</DataSource> </DataSource>
</xs:appinfo> </xs:appinfo>
</xs:annotation> </xs:annotation>
<xs:element name="dsQuery" msdata:IsDataSet="true" msdata:UseCurrentLocale="true" msprop:EnableTableAdapterManager="true" msprop:Generator_UserDSName="dsQuery" msprop:Generator_DataSetName="dsQuery"> <xs:element name="dsQuery" msdata:IsDataSet="true" msdata:UseCurrentLocale="true" msprop:EnableTableAdapterManager="true" msprop:Generator_DataSetName="dsQuery" msprop:Generator_UserDSName="dsQuery">
<xs:complexType> <xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="JobReportItemList" msprop:Generator_RowEvHandlerName="JobReportItemListRowChangeEventHandler" msprop:Generator_RowDeletedName="JobReportItemListRowDeleted" msprop:Generator_RowDeletingName="JobReportItemListRowDeleting" msprop:Generator_RowEvArgName="JobReportItemListRowChangeEvent" msprop:Generator_TablePropName="JobReportItemList" msprop:Generator_RowChangedName="JobReportItemListRowChanged" msprop:Generator_RowChangingName="JobReportItemListRowChanging" msprop:Generator_TableClassName="JobReportItemListDataTable" msprop:Generator_RowClassName="JobReportItemListRow" msprop:Generator_TableVarName="tableJobReportItemList" msprop:Generator_UserTableName="JobReportItemList"> <xs:element name="JobReportItemList" msprop:Generator_TableClassName="JobReportItemListDataTable" msprop:Generator_RowEvArgName="JobReportItemListRowChangeEvent" msprop:Generator_TableVarName="tableJobReportItemList" msprop:Generator_TablePropName="JobReportItemList" msprop:Generator_RowDeletingName="JobReportItemListRowDeleting" msprop:Generator_RowChangingName="JobReportItemListRowChanging" msprop:Generator_RowDeletedName="JobReportItemListRowDeleted" msprop:Generator_RowEvHandlerName="JobReportItemListRowChangeEventHandler" msprop:Generator_UserTableName="JobReportItemList" msprop:Generator_RowChangedName="JobReportItemListRowChanged" msprop:Generator_RowClassName="JobReportItemListRow">
<xs:complexType> <xs:complexType>
<xs:sequence> <xs:sequence>
<xs:element name="pidx" msprop:Generator_ColumnPropNameInRow="pidx" msprop:Generator_ColumnPropNameInTable="pidxColumn" msprop:Generator_ColumnVarNameInTable="columnpidx" msprop:Generator_UserColumnName="pidx" type="xs:int" minOccurs="0" /> <xs:element name="pidx" msprop:Generator_ColumnVarNameInTable="columnpidx" msprop:Generator_ColumnPropNameInRow="pidx" msprop:Generator_ColumnPropNameInTable="pidxColumn" msprop:Generator_UserColumnName="pidx" type="xs:int" />
<xs:element name="projectName" msprop:Generator_ColumnPropNameInRow="projectName" msprop:Generator_ColumnPropNameInTable="projectNameColumn" msprop:Generator_ColumnVarNameInTable="columnprojectName" msprop:Generator_UserColumnName="projectName" minOccurs="0"> <xs:element name="projectName" msprop:Generator_ColumnVarNameInTable="columnprojectName" msprop:Generator_ColumnPropNameInRow="projectName" msprop:Generator_ColumnPropNameInTable="projectNameColumn" msprop:Generator_UserColumnName="projectName">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="255" /> <xs:maxLength value="255" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
</xs:element> </xs:element>
<xs:element name="pdate" msdata:ReadOnly="true" msprop:Generator_ColumnPropNameInRow="pdate" msprop:Generator_ColumnPropNameInTable="pdateColumn" msprop:Generator_ColumnVarNameInTable="columnpdate" msprop:Generator_UserColumnName="pdate" minOccurs="0"> <xs:element name="pdate" msdata:ReadOnly="true" msprop:Generator_ColumnVarNameInTable="columnpdate" msprop:Generator_ColumnPropNameInRow="pdate" msprop:Generator_ColumnPropNameInTable="pdateColumn" msprop:Generator_UserColumnName="pdate" minOccurs="0">
<xs:simpleType> <xs:simpleType>
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:maxLength value="10" /> <xs:maxLength value="10" />
@@ -75,6 +100,26 @@ WHERE (pdate = @pdate)</CommandText>
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="HolydayUserList" msprop:Generator_TableClassName="HolydayUserListDataTable" msprop:Generator_TableVarName="tableHolydayUserList" msprop:Generator_TablePropName="HolydayUserList" msprop:Generator_RowDeletingName="HolydayUserListRowDeleting" msprop:Generator_RowChangingName="HolydayUserListRowChanging" msprop:Generator_RowEvHandlerName="HolydayUserListRowChangeEventHandler" msprop:Generator_RowDeletedName="HolydayUserListRowDeleted" msprop:Generator_UserTableName="HolydayUserList" msprop:Generator_RowChangedName="HolydayUserListRowChanged" msprop:Generator_RowEvArgName="HolydayUserListRowChangeEvent" msprop:Generator_RowClassName="HolydayUserListRow">
<xs:complexType>
<xs:sequence>
<xs:element name="uid" msprop:Generator_ColumnVarNameInTable="columnuid" msprop:Generator_ColumnPropNameInRow="uid" msprop:Generator_ColumnPropNameInTable="uidColumn" msprop:Generator_UserColumnName="uid">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="20" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="UserName" msdata:ReadOnly="true" msprop:Generator_ColumnVarNameInTable="columnUserName" msprop:Generator_ColumnPropNameInRow="UserName" msprop:Generator_ColumnPropNameInTable="UserNameColumn" msprop:Generator_UserColumnName="UserName" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="200" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice> </xs:choice>
</xs:complexType> </xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true"> <xs:unique name="Constraint1" msdata:PrimaryKey="true">
@@ -82,5 +127,9 @@ WHERE (pdate = @pdate)</CommandText>
<xs:field xpath="mstns:pidx" /> <xs:field xpath="mstns:pidx" />
<xs:field xpath="mstns:projectName" /> <xs:field xpath="mstns:projectName" />
</xs:unique> </xs:unique>
<xs:unique name="HolydayUserList_Constraint1" msdata:ConstraintName="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//mstns:HolydayUserList" />
<xs:field xpath="mstns:uid" />
</xs:unique>
</xs:element> </xs:element>
</xs:schema> </xs:schema>

View File

@@ -6,8 +6,9 @@
</autogenerated>--> </autogenerated>-->
<DiagramLayout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ex:showrelationlabel="False" ViewPortX="0" ViewPortY="0" xmlns:ex="urn:schemas-microsoft-com:xml-msdatasource-layout-extended" xmlns="urn:schemas-microsoft-com:xml-msdatasource-layout"> <DiagramLayout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ex:showrelationlabel="False" ViewPortX="0" ViewPortY="0" xmlns:ex="urn:schemas-microsoft-com:xml-msdatasource-layout-extended" xmlns="urn:schemas-microsoft-com:xml-msdatasource-layout">
<Shapes> <Shapes>
<Shape ID="DesignTable:JobReportItemList" ZOrder="2" X="40" Y="54" Height="305" Width="216" AdapterExpanded="true" DataTableExpanded="true" OldAdapterHeight="0" OldDataTableHeight="0" SplitterPosition="178" /> <Shape ID="DesignTable:JobReportItemList" ZOrder="3" X="40" Y="54" Height="305" Width="216" AdapterExpanded="true" DataTableExpanded="true" OldAdapterHeight="0" OldDataTableHeight="0" SplitterPosition="178" />
<Shape ID="DesignSources:QueriesTableAdapter" ZOrder="1" X="392" Y="70" Height="220" Width="189" AdapterExpanded="true" DataTableExpanded="true" OldAdapterHeight="0" OldDataTableHeight="0" SplitterPosition="216" /> <Shape ID="DesignSources:QueriesTableAdapter" ZOrder="2" X="392" Y="70" Height="220" Width="189" AdapterExpanded="true" DataTableExpanded="true" OldAdapterHeight="0" OldDataTableHeight="0" SplitterPosition="216" />
<Shape ID="DesignTable:HolydayUserList" ZOrder="1" X="260" Y="379" Height="115" Width="209" AdapterExpanded="true" DataTableExpanded="true" OldAdapterHeight="0" OldDataTableHeight="0" SplitterPosition="64" />
</Shapes> </Shapes>
<Connectors /> <Connectors />
</DiagramLayout> </DiagramLayout>

1
run_claude.bat Normal file
View File

@@ -0,0 +1 @@
claude --dangerously-skip-permissions