Compare commits

...

2 Commits

14 changed files with 343 additions and 155 deletions

View File

@ -20,6 +20,7 @@ public interface DrillingInputMapper {
public List<EgovMap> sPGetTblCsiByCid(HashMap<String, Object> params) throws SQLException;
public EgovMap getItemByCid(HashMap<String, Object> params) throws SQLException;
public EgovMap getItemByProjectCode(HashMap<String, Object> params) throws SQLException;
public int updateProjectCodeAndProjectStateCodeByCid(HashMap<String, Object> params) throws SQLException;
public int updateProjectCodeAndProjectStateCodeByProjectCode(HashMap<String, Object> params) throws SQLException;

View File

@ -138,7 +138,14 @@ public class DrillingInputServiceImpl implements DrillingInputService {
try {
EgovMap tbl = drillingInputMapper.getItemByCid( params );
EgovMap tbl = null;
Long lCid = MyUtil.getLongFromObject( params.get("CID") );
if( lCid == null ) {
tbl = drillingInputMapper.getItemByProjectCode( params );
params.put("CID", tbl.get("cid"));
} else {
tbl = drillingInputMapper.getItemByCid( params );
}
if( tbl != null ) {
HashMap<String, Object> updateProjectCodeParams = new HashMap<String, Object>();
@ -154,20 +161,11 @@ public class DrillingInputServiceImpl implements DrillingInputService {
}
}
if (nResult > 0) { // 업데이트가 성공했을 경우에만 이력 기록
HashMap<String, Object> histParams = new HashMap<String, Object>();
// 이전 상태값 (EgovMap은 보통 camelCase로 키를 반환합니다)
Object preStateCode = tbl.get("projectStateCode");
histParams.put("CID", params.get("CID"));
histParams.put("PROJECT_CODE", params.get("PROJECT_CODE"));
histParams.put("PRE_PROJECT_STATE_CODE", preStateCode != null ? preStateCode.toString() : null); // 이전 상태
histParams.put("PROJECT_STATE_CODE", params.get("PROJECT_STATE_CODE")); // 현재 변경된 상태
histParams.put("MOD_REASON", "지반정보 등록 프로젝트 연결"); // 변경 사유 (필요에 따라 파라미터로 받아서 설정 가능)
histParams.put("userId", userId);
drillingInputMapper.insertConstructSiteHist(histParams);
if ( 0 < nResult) { // 업데이트가 성공했을 경우에만 이력 기록
int nAffectedRows = insertTempConstructSiteInfo(request, tbl, updateProjectCodeParams, userId); // TEMP_CONSTRUCT_SITE_HIST에 이력도 남겨준다.
if( nAffectedRows == 0) {
System.out.println("TEMP_CONSTRUCT_SITE_HIST insert에 실패하였습니다. cid:" + tbl.get("cid"));
}
}
}
return params;
@ -185,8 +183,14 @@ public class DrillingInputServiceImpl implements DrillingInputService {
params.put("userId", userId);
try {
EgovMap tbl = drillingInputMapper.getItemByCid( params );
EgovMap tbl = null;
Long lCid = MyUtil.getLongFromObject( params.get("CID") );
if( lCid == null ) {
tbl = drillingInputMapper.getItemByProjectCode( params );
params.put("CID", tbl.get("cid"));
} else {
tbl = drillingInputMapper.getItemByCid( params );
}
if( tbl != null ) {
HashMap<String, Object> updateProjectCodeParams = new HashMap<String, Object>();
@ -200,7 +204,14 @@ public class DrillingInputServiceImpl implements DrillingInputService {
int nResult = drillingInputMapper.updateProjectCodeAndProjectStateCodeByProjectCode(updateProjectCodeParams);
if( nResult == 0 ) {
}
} else {
int nAffectedRows = insertTempConstructSiteInfo(request, tbl, updateProjectCodeParams, userId); // TEMP_CONSTRUCT_SITE_HIST에 이력도 남겨준다.
if( nAffectedRows == 0) {
System.out.println("TEMP_CONSTRUCT_SITE_HIST insert에 실패하였습니다. cid:" + tbl.get("cid"));
}
}
} else {
System.out.println("TEMP_CONSTRUCT_SITE_INFO에서 대상을 찾을 수 없습니다.");
}
return params;
} catch (SQLException e) {
@ -256,4 +267,23 @@ public class DrillingInputServiceImpl implements DrillingInputService {
throw new Exception( e.getMessage() );
}
}
private int insertTempConstructSiteInfo(HttpServletRequest request, EgovMap tbl, HashMap<String, Object> params, String userId) throws SQLException {
HashMap<String, Object> histParams = new HashMap<String, Object>();
// 이전 상태값 (EgovMap은 보통 camelCase로 키를 반환합니다)
Object preStateCode = tbl.get("projectStateCode");
histParams.put("CID", params.get("CID"));
histParams.put("PROJECT_CODE", params.get("PROJECT_CODE"));
histParams.put("PRE_PROJECT_STATE_CODE", preStateCode != null ? preStateCode.toString() : null); // 이전 상태
histParams.put("PROJECT_STATE_CODE", params.get("PROJECT_STATE_CODE")); // 현재 변경된 상태
histParams.put("MOD_REASON", "지반정보 등록 프로젝트 연결"); // 변경 사유 (필요에 따라 파라미터로 받아서 설정 가능)
histParams.put("userId", userId);
return drillingInputMapper.insertConstructSiteHist(histParams);
}
}

View File

@ -175,10 +175,10 @@ public class DrillingInquiryServiceImpl implements DrillingInquiryService {
projectStateCodeName = "검수 중";
break;
case 4:
projectStateCodeName = "수정 요청_";
projectStateCodeName = "수정 요청";
break;
case 5:
projectStateCodeName = "수정 요청";
projectStateCodeName = "검수 완료";
break;
case 6:
projectStateCodeName = "등록 완료";

View File

@ -1138,7 +1138,7 @@ public class LoginController {
url = "home/main_sitemap.jsp";
else
url = "index.do?cntyn=0";
}
}
}
}
} else {

View File

@ -97,7 +97,7 @@ public interface LoginMapper {
EgovMap selectSearchIniUserId(Map<String, Object> params);
public int checkWebMemberIn(Map<String, Object> map) throws Exception;
public int checkWebMemberIn(Map<String, Object> map) throws Exception;
String findProjectMasterCompanyNameByUserid(String userId);
String findProjectMasterCompanyCodeByUserid(String userId);

View File

@ -17,7 +17,7 @@ public interface LoginService {
Map<String, Object> selectWebMemberInLoginCount(Map<String, Object> map) throws Exception;
void insertWebRequestLog(Map<String, Object> map) throws Exception;
void updateWebMemberIn(Map<String, Object> map) throws Exception;
int insertSearchPassLog(Map<String, Object> map)throws Exception;
int insertSearchPassLog(Map<String, Object> map)throws Exception;
void pswdResetWebMemberIn(Map<String,Object> map) throws Exception;
Map<String, Object> selectSearchId(Map<String, Object> map) throws Exception;
Map<String, Object> selectSearchIdByNameAndPhoneAndDupinfoIsNullAndCertificationYnFalse(Map<String, Object> map) throws Exception;

View File

@ -119,6 +119,13 @@
</select>
<select id="getItemByProjectCode" parameterType="map" resultType="egovMap">
<![CDATA[
SELECT * FROM TEMP_CONSTRUCT_SITE_INFO WHERE TRIM(PROJECT_CODE) = #{PROJECT_CODE}
]]>
</select>
<update id="updateProjectCodeAndProjectStateCodeByCid" parameterType="map">
<![CDATA[

View File

@ -47,7 +47,7 @@ if (request.getSession().getAttribute("CLS") == null || "2".equals(request.getSe
<div class="page-sidebar inside-treeview">
<div class="treeview-project-name">
<p class="project-title">건설현장 관리</p>
<p class="project-value"><a href="/drilling/inquiry-project.do">프로젝트 조회</a></p>
<p class="project-value"><a href="/drilling/inquiry-project.do">관리 시추정보 현황</a></p>
<p class="project-value"><a href="/drilling/inquiry.do">건설현장 조회</a></p>
<p class="project-value value-is-active">건설현장 입력</p>
</div>

View File

@ -423,7 +423,7 @@ if (request.getSession().getAttribute("CLS") == null || "2".equals(request.getSe
<div class="page-sidebar">
<div class="treeview-project-name">
<p class="project-title">건설현장 관리</p>
<p class="project-value"><a href="/drilling/inquiry-project.do">프로젝트 조회</a></p>
<p class="project-value"><a href="/drilling/inquiry-project.do">관리 시추정보 현황</a></p>
<p class="project-value value-is-active">건설현장 조회</p>
<p class="project-value"><a href="/drilling/input.do">건설현장 입력</a></p>
</div>

View File

@ -4,10 +4,7 @@
<%
if (request.getSession().getAttribute("USERID") == null) {
%>
<script>alert('로그인후 이용하실 수 있습니다.');window.location.href='/index.do';</script>
<%
@ -15,9 +12,7 @@ if (request.getSession().getAttribute("USERID") == null) {
}
%>
<%
if (request.getSession().getAttribute("CLS") == null || "2".equals(request.getSession().getAttribute("CLS") ) == false ) {
%>
<script>alert('발주 기관 회원만 이용가능합니다.');window.location.href='/index.do';</script>
<%
@ -30,33 +25,161 @@ if (request.getSession().getAttribute("CLS") == null || "2".equals(request.getSe
<%@ include file="/include/inc_head_2021_new.jsp" %>
<!-- header start-->
<c:import url="/drilling/common/includeTopMenu.do" charEncoding="UTF-8" />
<!-- Tailwind CSS CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Google Fonts: Inter -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Noto+Sans+KR:wght@400;500;700&display=swap" rel="stylesheet">
<!-- header end-->
<style>
/* Minimal styles needed for this page */
</style>
<!-- javascript start-->
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
// 페이지 로드 시 이력 목록을 불러옵니다.
loadHistoryList();
});
/**
* 서버에 건설현장 이력 목록을 요청하는 함수
*/
function loadHistoryList() {
// '알림 내역' 전체 페이지이므로 row 파라미터를 제거하거나 늘립니다. (예: 1페이지의 기본값)
var url = '/drilling/statistics/hist-list.do?page=1'; // 5개 제한 제거
requesetGet(url, displayHistoryList, null); // 'requesetGet'은 원본의 오타를 그대로 유지
}
/**
* 상태 코드에 따라 아이콘과 색상, 텍스트를 반환하는 함수
*/
function getStatusInfo(statusCode) {
var status = {
name: '알 수 없음',
// 기본 아이콘: 캘린더 (기존 코드와 동일)
icon: '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="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>',
bgColor: 'bg-gray-500',
textColor: 'text-gray-600'
};
switch (String(statusCode)) {
case '0':
status.name = '미입력';
// 아이콘: 마이너스 (MinusCircle) - 비어있거나 시작 안 함
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>';
status.bgColor = 'bg-gray-500'; // 회색 (중립)
status.textColor = 'text-gray-600';
break; //
case '1':
status.name = '입력 중';
// 아이콘: 연필 (Pencil) - 수정/작성 중 (기존과 동일)
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.5L14.732 3.732z"></path></svg>';
status.bgColor = 'bg-blue-500'; // 파란색 (진행중)
status.textColor = 'text-blue-600';
break;
case '2':
status.name = '검수 준비 대기중';
// 아이콘: 시계 (Clock) - 대기 중
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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>';
status.bgColor = 'bg-yellow-500'; // 노란색 (대기)
status.textColor = 'text-yellow-600';
break; //
case '3':
status.name = '검수중';
// 아이콘: 돋보기 (Search) - 검토 중
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>';
status.bgColor = 'bg-yellow-500'; // 노란색 (대기/검토)
status.textColor = 'text-yellow-600';
break;
case '4':
status.name = '수정 요청';
// 아이콘: 느낌표 (ExclamationCircle) - 주의/수정 필요
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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>';
status.bgColor = 'bg-red-500'; // 빨간색 (거절/오류)
status.textColor = 'text-red-600';
break;
case '5':
status.name = '검수 완료';
// 아이콘: 체크 (CheckCircle) - 성공 (기존과 동일)
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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>';
status.bgColor = 'bg-green-500'; // 초록색 (완료/성공)
status.textColor = 'text-green-600';
break;
case '6':
status.name = '등록 완료';
// 아이콘: 체크 (CheckCircle) - 성공 (기존과 동일)
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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>';
status.bgColor = 'bg-green-500'; // 초록색 (완료/성공)
status.textColor = 'text-green-600';
break;
}
return status;
}
/**
* API 호출 결과를 받아 화면에 이력 목록을 표시하는 콜백 함수
*/
function displayHistoryList(response) {
// ▼▼▼ [수정] 대상 ID를 'notification-list-full'로 변경
var notificationList = document.getElementById('notification-list-full');
notificationList.innerHTML = ''; // 기존 목록 초기화
if (response && response.resultCode === 200 && response.datas) {
var datas = response.datas;
var contentHtml = '';
for (var i = 0; i < datas.length; i++) {
var item = datas[i];
var preStateInfo = getStatusInfo(item.preProjectStateCode);
var currentStateInfo = getStatusInfo(item.projectStateCode);
// ▼▼▼ [수정] 날짜/시간 파싱 (정적 HTML과 동일하게)
var ymd = '';
var hms = '';
if (item.modDt) {
var dateParts = item.modDt.split(' ');
ymd = dateParts[0] || '';
hms = (dateParts[1] || '').substring(0, 5); // HH:mm 까지만
}
// ▼▼▼ [수정] HTML 구조를 정적 페이지(notice.jsp)의 디자인에 맞춤
contentHtml +=
'<div class="flex items-start p-4 bg-gray-50 rounded-lg">' +
// 아이콘 (h-10, w-10, mr-4)
'<div class="' + currentStateInfo.bgColor + ' text-white rounded-full h-10 w-10 flex-shrink-0 flex items-center justify-center mr-4">' +
currentStateInfo.icon +
'</div>' +
// 텍스트 (flex-grow)
'<div class="flex-grow">' +
'<p class="text-3xl font-medium text-gray-800">\'' + item.constName + '\'</p>' +
'<p class="text-2xl text-gray-600">' +
'상태가 <span class="font-semibold ' + preStateInfo.textColor + '">' + preStateInfo.name + '</span>에서 ' +
'<span class="font-semibold ' + currentStateInfo.textColor + '">' + currentStateInfo.name + '</span>상태로 변경되었습니다.' +
'</p>' +
'</div>' +
// 날짜/시간 (text-right)
'<div class="text-right text-gray-500 text-xl flex-shrink-0" style="width: 130px;">' +
'<p>' + ymd + '</p>' +
'<p>' + hms + '</p>' +
'</div>' +
'</div>';
}
if (datas.length === 0) {
contentHtml = '<div class="p-4 text-center text-gray-500">최근 알림 내역이 없습니다.</div>';
}
notificationList.innerHTML = contentHtml;
} else {
notificationList.innerHTML = '<div class="p-4 text-center text-gray-500">알림 목록을 불러오는 데 실패했습니다.</div>';
console.error("Error fetching history list:", response.resultMessage);
}
}
</script>
<!-- javascript end-->
<!-- 페이지 컨테이너 시작 -->
<section class="drilling-page-container">
<div class="page-content-wrapper drilling inquiry">
<!-- 서브메뉴 시작 -->
<div class="page-sidebar-wrapper">
<div class="page-sidebar-wrapper">
<div class="page-sidebar">
<div class="treeview-project-name">
<p class="project-title">알림</p>
@ -65,84 +188,32 @@ if (request.getSession().getAttribute("CLS") == null || "2".equals(request.getSe
</div>
</div>
</div>
<!-- 서브메뉴 끝 -->
<!-- 콘텐츠 시작 -->
<div class="page-content">
<div class="page-content">
<div class="page-content-inner">
<!-- 카테고리 시작 -->
<div class="category-wrapper">
<div class="category-wrapper">
<ul class="page-category">
<li class="category-item"></li>
<li class="category-item">알림 내역</li>
</ul>
<a href="#" class="btn btn-help">도움말</a>
</div>
<!-- 카테고리 끝 -->
<h1 class="page-title-1depth">알림 내역</h1>
<!-- 내용 시작 -->
<div class="content-wrapper">
<!-- Main Content -->
<main class="w-full">
<h1 class="page-title-1depth">알림 내역</h1>
<div class="content-wrapper">
<main class="w-full">
<div class="bg-white p-6 rounded-lg shadow-md">
<div class="border-b pb-4 mb-4">
<h3 class="font-semibold text-gray-800 text-4xl">건설현장 프로젝트 상태 변경 이력</h3>
</div>
<div class="space-y-6">
<!-- Notification Item 1 -->
<div class="flex items-start p-4 bg-gray-50 rounded-lg">
<div class="bg-green-500 text-white rounded-full h-10 w-10 flex-shrink-0 flex items-center justify-center mr-4">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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>
</div>
<div class="flex-grow">
<p class="text-3xl font-medium text-gray-800">'충북선 달천 충주간' 프로젝트</p>
<p class="text-2xl text-gray-600">상태가 <span class="font-semibold text-yellow-600">검수중</span>에서 <span class="font-semibold text-green-600">검수 완료</span>로 변경되었습니다.</p>
</div>
<div class="text-right text-gray-500 text-xl">
<p>2025-08-27</p>
<p>14:30</p>
</div>
</div>
<!-- Notification Item 2 -->
<div class="flex items-start p-4 bg-gray-50 rounded-lg">
<div class="bg-blue-500 text-white rounded-full h-10 w-10 flex-shrink-0 flex items-center justify-center mr-4">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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>
</div>
<div class="flex-grow">
<p class="text-3xl font-medium text-gray-800">'제3연륙교 건설 공사' 프로젝트</p>
<p class="text-2xl text-gray-600">상태가 <span class="font-semibold text-green-600">검수 완료</span>에서 <span class="font-semibold text-blue-600">수정 요청</span>으로 변경되었습니다.</p>
</div>
<div class="text-right text-gray-500 text-xl">
<p>2025-08-26</p>
<p>11:15</p>
</div>
</div>
<!-- Notification Item 3 -->
<div class="flex items-start p-4 bg-gray-50 rounded-lg">
<div class="bg-yellow-500 text-white rounded-full h-10 w-10 flex-shrink-0 flex items-center justify-center mr-4">
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="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 class="flex-grow">
<p class="text-3xl font-medium text-gray-800">'수도권 제2순환고속도로' 프로젝트</p>
<p class="text-2xl text-gray-600">상태가 <span class="font-semibold text-gray-600">미입력</span>에서 <span class="font-semibold text-yellow-600">검수중</span>으로 변경되었습니다.</p>
</div>
<div class="text-right text-gray-500 text-xl">
<p>2025-08-25</p>
<p>09:05</p>
</div>
</div>
<div id="notification-list-full" class="space-y-6">
<div class="p-4 text-center text-gray-500">알림 목록을 불러오는 중입니다...</div>
</div>
</div>
</div>
</main>
</div>
<!-- 내용 끝 -->
</div>
</div>
</div>
<!-- 콘텐츠 끝 -->
</div>
</div>
</section>
<!-- 페이지 컨테이너 끝 -->
<div id="calenderDiv" class="trViewOff" style="position:absolute;"></div>
<%@ include file="/include/inc_footer_2021_new.jsp" %>
<%@ include file="/include/inc_footer_2021_new.jsp" %>

View File

@ -290,7 +290,7 @@ document.addEventListener('DOMContentLoaded', function() {
*/
function loadHistoryList() {
// 알림 내역은 최신 3개만 가져오도록 설정
var url = '/drilling/statistics/hist-list.do?page=1&rows=3';
var url = '/drilling/statistics/hist-list.do?page=1&rows=5';
requesetGet(url, displayHistoryList, null);
}
@ -300,6 +300,7 @@ function loadHistoryList() {
function getStatusInfo(statusCode) {
var status = {
name: '알 수 없음',
// 기본 아이콘: 캘린더 (기존 코드와 동일)
icon: '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="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>',
bgColor: 'bg-gray-500',
textColor: 'text-gray-600'
@ -308,30 +309,51 @@ function getStatusInfo(statusCode) {
switch (String(statusCode)) {
case '0':
status.name = '미입력';
break;
// 아이콘: 마이너스 (MinusCircle) - 비어있거나 시작 안 함
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>';
status.bgColor = 'bg-gray-500'; // 회색 (중립)
status.textColor = 'text-gray-600';
break; //
case '1':
status.name = '입력 중';
// 아이콘: 연필 (Pencil) - 수정/작성 중 (기존과 동일)
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.5L14.732 3.732z"></path></svg>';
status.bgColor = 'bg-blue-500';
status.bgColor = 'bg-blue-500'; // 파란색 (진행중)
status.textColor = 'text-blue-600';
break;
case '2':
status.name = '검수 준비 대기중';
// 아이콘: 시계 (Clock) - 대기 중
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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>';
status.bgColor = 'bg-yellow-500'; // 노란색 (대기)
status.textColor = 'text-yellow-600';
break; //
case '3':
status.name = '검수중';
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16l4-4m0 0l4-4m-4 4v6m0-6H8a2 2 0 00-2 2v6a2 2 0 002 2h8a2 2 0 002-2v-6a2 2 0 00-2-2h-2"></path></svg>';
status.bgColor = 'bg-yellow-500';
// 아이콘: 돋보기 (Search) - 검토 중
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>';
status.bgColor = 'bg-yellow-500'; // 노란색 (대기/검토)
status.textColor = 'text-yellow-600';
break;
case '5':
case '4':
status.name = '수정 요청';
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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>';
status.bgColor = 'bg-red-500';
// 아이콘: 느낌표 (ExclamationCircle) - 주의/수정 필요
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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>';
status.bgColor = 'bg-red-500'; // 빨간색 (거절/오류)
status.textColor = 'text-red-600';
break;
case '5':
status.name = '검수 완료';
// 아이콘: 체크 (CheckCircle) - 성공 (기존과 동일)
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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>';
status.bgColor = 'bg-green-500'; // 초록색 (완료/성공)
status.textColor = 'text-green-600';
break;
case '6':
status.name = '등록 완료';
// 아이콘: 체크 (CheckCircle) - 성공 (기존과 동일)
status.icon = '<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><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>';
status.bgColor = 'bg-green-500';
status.bgColor = 'bg-green-500'; // 초록색 (완료/성공)
status.textColor = 'text-green-600';
break;
}
@ -368,7 +390,7 @@ function displayHistoryList(response) {
'<p class="text-3xl font-medium text-gray-800">\'' + item.constName + '\'</p>' +
'<p class="text-2xl text-gray-600">' +
'상태가 <span class="font-semibold ' + preStateInfo.textColor + '">' + preStateInfo.name + '</span>에서 ' +
'<span class="font-semibold ' + currentStateInfo.textColor + '">' + currentStateInfo.name + '</span>로 변경되었습니다.' +
'<span class="font-semibold ' + currentStateInfo.textColor + '">' + currentStateInfo.name + '</span>상태로 변경되었습니다.' +
'</p>' +
'</div>' +
'</div>';

View File

@ -225,7 +225,7 @@ if (request.getSession().getAttribute("CLS") == null || "2".equals(request.getSe
<div class="page-sidebar">
<div class="treeview-project-name">
<p class="project-title">건설현장 관리</p>
<p class="project-value value-is-active">프로젝트 조회</p>
<p class="project-value value-is-active">관리 시추정보 현황</p>
<p class="project-value"><a href="/drilling/inquiry.do">건설현장 조회</a></p>
<p class="project-value"><a href="/drilling/input.do">건설현장 입력</a></p>
</div>
@ -240,12 +240,12 @@ if (request.getSession().getAttribute("CLS") == null || "2".equals(request.getSe
<div class="category-wrapper">
<ul class="page-category">
<li class="category-item"></li>
<li class="category-item">프로젝트 조회</li>
<li class="category-item">관리 시추정보 현황</li>
</ul>
<a href="#" class="btn btn-help">도움말</a>
</div>
<!-- 카테고리 끝 -->
<h1 class="page-title-1depth">프로젝트 조회</h1>
<h1 class="page-title-1depth">관리 시추정보 현황</h1>
<!-- 내용 시작 -->
<div class="content-wrapper">
<div class="content1">

View File

@ -12,6 +12,43 @@ var extFile = "<%=fileCmmn.getFileList("IMG")%>";
var extFileList = extFile.split(",");
var selectedSeq = "";
//kendoGrid에서 중복된 행을 빨간색으로 흔드는 함수
function highlightDuplicateRows(grid, indices) {
var trs = grid.tbody.find("tr");
for (var i = 0; i < indices.length; i++) {
var rowIndex = indices[i];
var rowElement = trs[rowIndex];
// CSS 클래스 추가
kendoJQuery(rowElement).addClass("k-row-duplicate-shake");
}
// 2초 후 클래스 제거
setTimeout(function() {
kendoJQuery(".k-row-duplicate-shake").removeClass("k-row-duplicate-shake");
}, 2000);
}
//중복 강조를 위한 CSS 추가
function fn_addHighlightStyles() {
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = `
@keyframes shake {
10%, 90% { transform: translate3d(-1px, 0, 0); }
20%, 80% { transform: translate3d(2px, 0, 0); }
30%, 50%, 70% { transform: translate3d(-4px, 0, 0); }
40%, 60% { transform: translate3d(4px, 0, 0); }
}
.k-row-duplicate-shake {
background-color: #ffcccc !important;
animation: shake 0.5s;
animation-iteration-count: infinite;
}
`;
document.head.appendChild(style);
}
// Grid1 데이터 조회
function selectGrid1() {
@ -298,6 +335,54 @@ function fn_save(rUrl) {
return false;
}
// ----------------------- [수정됨] kictGrid2 시간(sec) 중복 체크 시작 -----------------------
var grid2 = kendoJQuery("#kictGrid2").data("kendoGrid");
var data2 = grid2.dataSource._data; // data2 변수 재사용
var seenTimes = {};
var duplicateIndices = [];
for(var i=0; i<data2.length; i++){
var row = data2[i];
var timeValue = row.fieldperSubTime; // 시간(sec) 컬럼
// 빈 값은 중복 체크에서 제외
if (timeValue === "" || timeValue === null || timeValue === undefined) {
continue;
}
var key = timeValue.toString(); // 키 값으로 사용
if (seenTimes[key]) {
// 중복된 값을 발견하면 인덱스 저장
if (seenTimes[key].first) {
duplicateIndices.push(seenTimes[key].index);
seenTimes[key].first = false;
}
duplicateIndices.push(i);
}
seenTimes[key] = { index: i, first: true };
}
if (duplicateIndices.length > 0) {
// 중복된 값을 포함하여 알림 메시지 생성
var duplicatedValues = "";
var uniqueDuplicates = new Set();
for (var i = 0; i < duplicateIndices.length; i++) {
var row = data2[duplicateIndices[i]];
var value = row.fieldperSubTime;
uniqueDuplicates.add(value);
}
duplicatedValues = Array.from(uniqueDuplicates).join(", ");
alert("시간(sec) 데이터에 중복이 있습니다: " + duplicatedValues + ". 중복을 확인 후 다시 저장해 주십시오.");
// 중복된 행을 시각적으로 강조
highlightDuplicateRows(grid2, duplicateIndices);
return false; // 저장 중단
}
// ----------------------- [수정됨] kictGrid2 시간(sec) 중복 체크 끝 -----------------------
// ----------------------- kendoGrid XML 구조저장 시작 -----------------------
var grid1 = kendoJQuery("#kictGrid1").data("kendoGrid");
@ -331,9 +416,9 @@ function fn_save(rUrl) {
];
if(fn_saveNumberCheckKendo("ROW", dataSource1, grid1, "gridCheck1", 0, rowInfo1, rowInfoItem1) == false)return false;
var grid2 = kendoJQuery("#kictGrid2").data("kendoGrid");
// var grid2 = kendoJQuery("#kictGrid2").data("kendoGrid"); // 위에서 이미 선언됨
var dataSource2 = grid2.dataSource;
var data2 = dataSource2._data;
// var data2 = dataSource2._data; // 위에서 이미 선언됨
var kendoRowCount2 = dataSource2._view.length; // 가로(행) 갯수
var kendoColCount2 = grid2.columns.length; // 세로(열) 갯수
@ -386,12 +471,12 @@ function fn_save(rUrl) {
document.getElementById("colCount").value = kendoColCount1;
document.frmPm.rowDelFileArr.value = rowDelFileArr;
document.frmPm.topGridRowDelete.value = topGridRowDelete;
document.frmPm.SEQ.value = selectedSeq; //현재 상위 그리드에서 선택되어있는 SEQ
document.frmPm.SEQ.value = selectedSeq; //현재 상위 그리드에서 선택되어있는 SEQ
var _seq = selectedSeq;
$('#beforeSEQ').val("");
// 2019.10.10 이미지 업로드 필수 수정
// 2019.10.10 이미지 업로드 필수 수정
var fileImg = $("#GRAPH_IMAGE_"+_seq).val();
var fileImg_bk = $("#OLD_GRAPH_IMAGE_"+_seq).val();
if(fileImg_bk === "null" ){
@ -758,25 +843,16 @@ function fn_grid_refresh(){
</script>
<!-- 헤더 시작 -->
<c:import url="/manage/includeTopInput.do" />
<!-- 헤더 끝 -->
<!-- 페이지 컨테이너 시작 -->
<section class="page-container">
<div class="page-content-wrapper">
<!-- 서브메뉴 시작 -->
<c:import url="/include_left_tree_input.do" />
<!-- 서브메뉴 끝 -->
<!-- 컨텐츠 시작 -->
<div class="page-content">
<div class="page-content-inner">
<!-- 카테고리 시작 -->
<div class="category-wrapper">
<ul class="page-category">
<li class="category-item" id="category_1dep"></li>
@ -786,23 +862,16 @@ function fn_grid_refresh(){
<a href="javascript:;" class="btn btn-help start-tour" onClick="fn_help_tour_confirm();">도움말</a>
</div>
<!-- 카테고리 끝 -->
<h1 class="page-title-1depth"><span>기본현장시험 정보</span></h1>
<!-- 내용 시작 -->
<div class="content-wrapper">
<!-- search start -->
<div class="contents">
<!-- 프로젝트 정보 출력 -->
<c:import url="/com/includeProjectInfo.do" />
<!-- Tab 출력 -->
<c:import url="/com/includeTopLabInfo.do" />
<!-- Tab 컨텐츠 출력 -->
<div class="tab-content">
<div class="table-top-control">
@ -826,6 +895,7 @@ function fn_grid_refresh(){
kendoJQuery(document).ready(function () {
selectGrid1();
fn_kendoGrid2(null); // 20201005 ROW 셀렉트시 탭,엔터키 에러 수정
fn_addHighlightStyles(); // [수정됨] 중복 강조 CSS 함수 호출
});
function onDataBound1(e) {
@ -1177,22 +1247,11 @@ function fn_grid_refresh(){
</div>
</div>
<!-- search end -->
</div>
</div>
<!-- 내용 끝 -->
</div>
</div>
<!-- 컨텐츠 끝 -->
</div>
</div>
</section>
<!-- 페이지 컨테이너 끝 -->
<!-- footer 시작 -->
<c:import url="/com/includeFooterInput.do"/>
<!-- footer 끝 -->
<c:import url="/com/includeFooterInput.do"/>

View File

@ -652,8 +652,6 @@ function initApp(param){
"WEB_STEEP_SLOPE",
O2MAP_URL,
{
isBaseLayer: false,
visibility: false,
layers : T_WEB_STEEP_SLOPE,
transparent : true,
format : "image/png",
@ -661,7 +659,7 @@ function initApp(param){
}, {
singleTile : false,
isBaseLayer : false,
visibility: getQueryString("masterCompanyCode") === null ? true : true,
visibility: false,
transitionEffect: "resize",
buffer : 0,
removeBackBufferDelay : 0