wyh 2024-10-24
팩스발송 주소록 불러오기, 엑셀불러오기 기능 수정
@7559e22a1b64e803eab2cd75789ec3af50c66cc5
src/main/webapp/WEB-INF/jsp/cmm/uss/umt/EgovGnrlUserManage.jsp
--- src/main/webapp/WEB-INF/jsp/cmm/uss/umt/EgovGnrlUserManage.jsp
+++ src/main/webapp/WEB-INF/jsp/cmm/uss/umt/EgovGnrlUserManage.jsp
@@ -655,8 +655,8 @@
 		                    </td>		                    
 							</c:if>
 							<td <c:if test="${result.smishingYn eq 'Y'}">class="smishing"</c:if> title="<c:out value="${result.loginLastDate}"/>">
-								<fmt:parseDate value="${result.loginLastDate}" var="loginLastDateValue" pattern="yyyy-MM-dd HH:mm"/>
-								<fmt:formatDate value="${loginLastDateValue}" pattern="MM-dd HH:mm"/>																						
+								<%-- <fmt:parseDate value="${result.loginLastDate}" var="loginLastDateValue" pattern="yyyy-MM-dd HH:mm"/>
+								<fmt:formatDate value="${loginLastDateValue}" pattern="MM-dd HH:mm"/> --%>																						
 		                    </td>		                    
 						</tr>
 						<c:if test="${userSearchVO.mberSttus == 'B'}">
src/main/webapp/WEB-INF/jsp/web/fax/faxDataView.jsp
--- src/main/webapp/WEB-INF/jsp/web/fax/faxDataView.jsp
+++ src/main/webapp/WEB-INF/jsp/web/fax/faxDataView.jsp
@@ -5,21 +5,33 @@
 <%@ taglib prefix="ec" uri="/WEB-INF/tld/ecnet_tld.tld"%>
 <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
 <%@ page import="itn.com.cmm.LoginVO" %>
+
+<!--
 <script>document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1"></' + 'script>')</script>
+-->
+
 <script src="/publish/js/content.js"></script>
 <!-- 스프레드시트(타뷸레이터)관련 js -->
 <script src="/js/user/fax/tabulator.js"></script>
 <!-- 주소록관련 js -->
 <script src="/js/user/fax/addr.js"></script>
 <!-- 엑셀불러오기관련 js -->
-<script src="/js/user/fax/exelLoad.js"></script>
+<script src="/js/user/fax/exelUpload.js"></script>
+
+<!-- 주소록 유효성 체크 공통유틸로 인해 추가 -->
+<script type="text/javascript" src="<c:url value='/js/web/addr/cmn.js?date=202409021440'/>"></script>
 
 <script type="text/javascript" src="<c:url value='/js/txtSpecialReplace.js?date=202209210001'/>"></script>
 <!-- 현재 jsp에서 사용하는 file 관련 js  -->
 <script type="text/javascript" src="<c:out value='/js/user/fax/file.js' />"></script>
 <script type="text/javascript">
 	var loginVO = '${loginVO}';
-
+	
+	var tableL = null;		//받는사람 연락처 Tabulator 변수
+	var tableAddr = null;	//주소록 불러오기 팝업 Tabulator 변수
+	var tableExcel = null;	//엑셀 불러오기 팝업 Tabulator 변수
+	var tableError = null;	//엑셀 오류 주소록 상세  팝업 Tabulator 변수
+	
 	$(document).ready(function(){
 		
 		//엑섹불러오기 버튼 클릭시 파일 첨부 실행
@@ -50,11 +62,6 @@
 				alert("팩스발송 서비스는 로그인 후 이용 가능합니다.");
 				return false;
 			}
-			
-			/* if(!moneyChk()){
-				return false;
-			} */
-			
 			
 			if(!valueChk()){
 				return false;
@@ -117,8 +124,6 @@
 				return false;
 			}
 		});		
-		
-		
 	});
 	
 	
@@ -154,7 +159,6 @@
 			addPhoneInfo(tableData)
 			
 		}
-		
 	}
 	
 	function moneyChk(){
@@ -218,13 +222,6 @@
 		return true;
 	}
 	
-	//주소록 팝업 닫기 기능
-	function addrClose(){
-		$(".closeAddr").trigger("click");
-		//주소록 레이어 팝업의 Tabulator 데이터 지워주기
-		tableAddr.clearData();
-	}
-	
 	/**
 	 * @description 금액 계산 function
 	 */
@@ -281,26 +278,38 @@
 		location.href="<c:url value='/web/mjon/fax/faxSendList.do'/>";
 	}
 	
-
+	//전체 데이터 갯수 구하는 함수
+	function updateTotCnt(data){
+		var rowTotCnt = data;
+		$("#rowTotCnt").text(numberWithCommas(rowTotCnt));
+	}
 
 </script>
 
-	<form id="convertForm" name="convertForm" action="">
-		<input type="hidden" id="faxConvertSeq" name="faxConvertSeq" value="" />
-		<input type="hidden" id="faxConvertFilePath" name="faxConvertFilePath" value="" /> <!-- 변환파일 경로  -->
-	</form>
-	<form id="faxSendForm" name="faxSendForm" action="">
-		<input type="hidden" id="subject" name="subject" value="" />
-		<input type="hidden" id="callToList" name="callToList" value="" />
-		<!-- 문자온 법인폰 번호 -->
-	<!-- 	<input type="hidden" id="callFrom" name="callFrom" value="15518011" />  -->
-		<input type="hidden" id="nameList" name="nameList" value="" />
-		<input type="hidden" id="faxConvertSeq" name="faxConvertSeq" value="" />
-		<input type="hidden" id="reserveYn" name="reserveYn" value="N" />
-		<input type="hidden" id="sendDate" name="sendDate" value="" />
-		<input type="hidden" id="totalEa" name="totalEa" value="" /> 
-	</form>
+<form id="convertForm" name="convertForm" action="">
+	<input type="hidden" id="faxConvertSeq" name="faxConvertSeq" value="" />
+	<input type="hidden" id="faxConvertFilePath" name="faxConvertFilePath" value="" /> <!-- 변환파일 경로  -->
+</form>
 
+<form id="faxSendForm" name="faxSendForm" action="">
+	<input type="hidden" id="subject" name="subject" value="" />
+	<input type="hidden" id="callToList" name="callToList" value="" />
+	<!-- 문자온 법인폰 번호 -->
+	<input type="hidden" id="nameList" name="nameList" value="" />
+	<input type="hidden" id="faxConvertSeq" name="faxConvertSeq" value="" />
+	<input type="hidden" id="reserveYn" name="reserveYn" value="N" />
+	<input type="hidden" id="sendDate" name="sendDate" value="" />
+	<input type="hidden" id="totalEa" name="totalEa" value="" /> 
+</form>
+
+<div class="loading_execl_layer">
+	<div class="loading_container">
+		<div class="bar"></div>
+		<div class="text">Loading</div>
+	</div>
+</div>
+
+<div>
 	<div class="inner">
 		<!-- send top -->
 		<div class="send_top">
@@ -319,8 +328,7 @@
 					</ul>
 				</div>
 				<!--// tab button 끝-->
-			
-			
+				
 				<!-- tab content1 -->
 				<div class="tap_content current" id="tab_content_1">
 					<div class="send_general">
@@ -452,13 +460,8 @@
 													</div>
 													<div class="list_bottom_right">
 														<p>총 <span class="c_e40000" id="rowTotCnt">0</span>건 / 중복 <span class="c_002c9a" id="rowDupCnt">0</span>건</p>
-														
-														<!-- <button type="button" class="address_reg2 addressregi_btn">주소록에 등록</button> -->
 													</div>
 												</div>
-	<!-- 											<div class="btn_popup_wrap">  -->
-	<!-- 												<button type="button" id="sendBtn" class="btnType btnType7 tab2">발송</button> -->
-	<!-- 											</div> -->
 											</div>
 										</td>
 									</tr>
@@ -469,8 +472,6 @@
 													<div class="final_pay">
 														<div class="pay_info_list">
 															<p>발송금액 :</p>
-	<!-- 														<div class="info" id="repPriceTxt" style="display: none;"> -->
-	<!-- 														</div> -->
 														</div>
 														<p class="price"><span id="repPriceTxt"></span><span id="totalPriceTxt">0</span> 원<span></span></p>
 													</div>
@@ -550,8 +551,6 @@
 		<input name="moveAddrFlag" type="hidden" value="N"/>
 		<input name="addrIdList" type="hidden" value=""/>
 	</form>
-
-
 </div>
 
 
@@ -566,7 +565,7 @@
 	<div class="popup-com import_layer popup06" tabindex="0" data-tooltip-con="popup06" data-focus="popup06" data-focus-prev="popup06-close" style="width: 1000px;z-index:98">
 		<div class="popup_heading">
 			<p><span>주소록 불러오기</p>
-			<button type="button" onClick="javascript:addrClose(); return false;">
+			<button type="button" onClick="javascript:addrToList_close(); return false;">
 			<img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
 		</div>
 		<div class="layer_in">
@@ -590,9 +589,6 @@
 							<div id="addrGroupLoad">
 							</div>
 						</div>
-						<!-- <div class="popup_btn">
-							<button type="button" class="btnType" onClick="javascript:fnSelectAddrGrpList(); return false;">선택 그룹 추가</button>
-						</div> -->
 					</div>
 					<div class="adr_pop_right">
 						<div class="clearfix">
@@ -614,8 +610,9 @@
 							<!--// table -->
 						</div>
 						<div class="popup_btn_wrap2">
-							<button type="button" onClick="javascript:addrToList(); return false;">추가</button>
-							<button type="button" onClick="javascript:addrClose(); return false;">닫기</button>
+							<button type="button" onClick="javascript:addrToList_advc('all'); return false;">전체추가</button>
+							<button type="button" onClick="javascript:addrToList_advc('select'); return false;">선택추가</button>
+							<button type="button" onClick="javascript:addrToList_close(); return false;">닫기</button>
 						</div>
 						<%-- 주소록 레이어 팝업 닫기 실행 코드 --%>
 						<input type="hidden" name="btnAddrClose" id="btnAddrClose" class="tooltip-close closeAddr" data-focus="popup06-close" />         
@@ -628,145 +625,226 @@
 <!--// 주소록 불러오기 -->
 
 <!-- 엑셀 불러오기 -->
-<form id="excelForm" name="excelForm" method="post">
-	<div class="tooltip-wrap">
-		<div class="popup-com import_layer popup02" tabindex="0" data-tooltip-con="popup02" data-focus="popup02" data-focus-prev="popup02-close">
-			<div class="popup_heading">
-				<p><span>엑셀</span> 불러오기</p>
-				<button type="button" class="tooltip-close" data-focus="popup02-close"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
-			</div>
-			<div class="layer_in">
-				<!-- 엑셀파일 불러오기 -->
-				<div class="hascont">
-					<div class="titBox">
-						<p>- 최대 2만 건까지 등록할 수 있습니다.</p>
-						<p>- [엑셀 불러오기]시 문서의 A, B, C, D열을 불러옵니다.(지원하는 파일 형식 : xls, xlsx)</p>
-<!-- 						<p>- 이름 : 20byte, [*1*] [*2*] : 40byte까지 입력 가능합니다.</p> -->
-						<p>- 이름 : 20byte까지 입력 가능합니다.</p>
-						<p>- 휴대폰 항목은 숫자, 하이픈(-)만 인식하며, 번호 앞에 0이 생략되어도 정상 등록됩니다.
-						</p>
-						<!-- <button type="button" class="excel_btn" onclick="location.href='/cmm/fms/FileDown.do?atchFileId=FILE_000000000011651&fileSn=1'"><i></i>샘플파일 다운로드</button> -->
-						<button type="button" class="excel_btn" onclick="location.href='/download/msg/팩스_엑셀주소록_등록양식.xlsx'"><i class="downroad"></i>샘플파일 다운로드</button>
+<div class="tooltip-wrap">
+	<div class="popup-com adr_layer popup02" tabindex="0" data-tooltip-con="popup02" data-focus="popup02" data-focus-prev="popup02-close" style="width: 1000px;">
+		<div class="tooltip-wrap">
+			<div class="popup-com adr_layer adr_popup14" tabindex="0" data-tooltip-con="adr_popup14" data-focus="adr_popup14" data-focus-prev="adr_popu14-close" style="width: 450px;">
+				<div class="popup_heading">
+					<p>주소록 상세 결과</p>
+					<button type="button" class="tooltip-close" data-focus="adr_popup14-close"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
+				</div>
+				<div class="layer_in" style="padding:30px 20px;">
+					<div class="table_top">
+						<p>
+						총 <span class="c_e40000" id="errorPopTotCnt">0</span>건 
+						/ 중복 <span class="c_002c9a" id="errorPopDupCnt">0</span>건
+						/ 오류 <span class="c_002c9a" id="errorPopErrorCnt">0</span>건</p>
+						<button type="button" class="excel_btn btnType" id="errorExcelBtn"><i class="downroad"></i>엑셀 다운로드</button>
 					</div>
-					<div class="attachedFile">
-						<label for="" class="attachedFile_label">첨부파일</label>
-						<input type="text" id="excelNm" readonly>
-						<input type="file" id="excelFile" accept=".xls, .xlsx" onchange="excelExport(event); return false;" style="display:none"/>
-						<button type="button" class="btnType btnType6 c3">찾아보기</button>
-						<p><span class="vMiddle">*</span> 첨부된 파일은 <span class="c_e40000">[추가]버튼을 클릭</span>하셔야 받는 사람에 등록됩니다.</p>
+					<div class="tb_wrap adr_list" id="tabulator_error">
+						<!-- $tableError 참고  -->
 					</div>
-				</div><!--// 엑셀파일 불러오기 -->
-				<div class="popup_btn_wrap2">
-					<button type="button" class="tooltip-close" data-focus="popup02-close"  data-focus-next="popup02" id="excelAdd">추가</button>
-					<button type="button" class="tooltip-close" data-focus="popup02-close"  data-focus-next="popup02">닫기</button>                      
+					<ul class="cf_text_ul">
+						<li>*중복번호는 하나의 번호만 등록됩니다.</li>
+						<li>*팩스번호 형식에 맞지 않는 데이터는 삭제 후 업로드 됩니다.</li>
+						<li>ex) 발송불가 특수문자, 자릿수 오류 등</li>
+					</ul>
+					<div class="popup_btn_wrap2">
+						<button type="button" class="tooltip-close" data-focus="adr_popup14-close" data-focus-next="adr_popup14">닫기</button>                      
+					</div>
 				</div>
 			</div>
 		</div>
+	
+		<div class="popup_heading">
+			<p>엑셀 불러오기</p>
+			<button type="button" class="tooltip-close" id="closeBtn" data-focus="popup02-close"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
+		</div>
+		<div class="layer_in" style="padding: 25px 30px;">
+		
+			<!-- 엑셀입력 -->
+			<div class="popCont current pop_more_cont" id="popCont_1">
+				<div class="titBox">
+					<p>- 최대 2만 건까지 등록할 수 있습니다.</p>
+					<p>- [엑셀 불러오기]시 문서의 A, B열을 불러옵니다.(지원하는 파일 형식 : xls, xlsx)</p>
+					<p>- 이름 : 20byte까지 입력 가능합니다.</p>
+					<p>- 팩스 번호는 지역번호(02, 031, 033 등), 타사부가번호(030*, 050*, 060, 070, 080, 1**)로 시작하는 번호만 발송 가능합니다. </p>
+				</div>
+				<div class="pop_more_wrap">
+						<button type="button" class="pop_more" onclick="popMore(this);">더보기<i></i></button>
+				</div>
+			</div>
+			<!--// 엑셀입력 -->
+		
+			<!-- 공통 -->
+			<div>
+				<table class="layer_tType1">
+					<caption>엑셀입력 표</caption>
+					<colgroup>
+						<col style="width: 95px">
+						<col style="width: auto">
+					</colgroup>
+					<tbody>
+						<tr>
+							<td colspan="2" style="padding:20px 0;">
+								<div class="file_upload_wrap" style="width:100%;display:flex;">
+									<div class="file_add exel_upload_area">
+										<p><img src="/publish/images/content/file_add.png" alt="파일 붙여넣기">마우스로 엑셀파일을 여기에 끌어다 놓으세요</p>
+									</div>
+									<input type="file" id="excelFile" accept=".xls, .xlsx" style="display:none"/>
+									<button type="button" class="excel_btn2 btnType c3"><i class="uproad"></i>엑셀파일 업로드</button>
+								</div>
+							</td>
+						</tr>
+					</tbody>
+				</table>
+			</div>
+		            
+			<div class="excel_middle2">
+				<p>
+					총 <span class="c_e40000 fwBold" id="excelRowTotCnt">0</span>건 
+					/ 중복 <span class="c_002c9a fwBold" id="excelRowDupCnt">0</span>건
+					/ 오류 <span class="c_002c9a fwBold" id="excelRowErrorCnt">0</span>건
+					<button type="button" class="btn_list_detail" data-tooltip="adr_popup14"><img src="/publish/images/search.png"></button>
+				</p>
+			</div>
+			<div class="adr_excel" style="margin-top: 13px; overflow-x:auto;">
+				<!-- thead -->
+				<div class="adr_hd select_adr_hd msg" data-group="tableExcel">
+					<div style="width: 40px;"></div>
+					<div style="width: 100px;"></div>
+					<div style="width: 400px;">
+						<label for="" class="label"></label>
+						<select class="field-selector">
+							<option value="">선택하기</option>
+							<option value="addrNm">이름</option>
+							<option value="addrFaxNo">팩스번호</option>
+						</select>
+					</div>
+					<div style="width: 400px;">
+						<label for="" class="label"></label>
+						<select class="field-selector">
+							<option value="">선택하기</option>
+							<option value="addrNm">이름</option>
+							<option value="addrFaxNo">팩스번호</option>
+						</select>
+					</div>
+				</div>
+			</div>					
+			<div class="drag_drop_wrap callList_includ_box" id="tabulator_excel"></div>
+			<div class="excel_middle">
+				<div class="select_btnWrap clearfix">
+					<div>
+						<button type="button" id="allDel"><i class="remove_img"></i>전체삭제</button>
+						<button type="button" id="in_select_del"><i class="remove_img"></i>선택삭제</button>
+					</div>
+				</div>
+			</div>
+			<!--// 공통 -->     
+			
+			<div class="popup_btn_wrap2" style="margin: 0 auto 30px auto;">
+				<button type="button" id="btnAddrMassReg">추가</button>
+				<button type="button" id="btnAddrMassClose" class="tooltip-close" data-focus="adr_popup01-close"  data-focus-next="popup02">닫기</button>                      
+			</div>
+		</div>
 	</div>
-</form>
+</div>
 <!--// 엑셀 불러오기 -->
+
 <!--// 전송내역 팝업  시작-->
 <div class="tooltip-wrap">
-		<div class="popup-com history_layer popup03" tabindex="0" data-tooltip-con="popup03" data-focus="popup03" data-focus-prev="popup03-close">
-			<div class="popup_heading">
-				<p><span>전송내역</p>
-				<button type="button" class="tooltip-close" data-focus="popup03-close" id="btnLatestAddPhoneClose"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
-			</div>
-			<div class="layer_in">
-				<!-- tab button -->
-				<ul class="tabType6"> 
-					<li class="tab active"><button type="button" onclick="TabType(this,'1');">최근 전송내역</button></li>
-					<li class="tab"><button type="button" onclick="TabType(this,'2');">자주보내는 번호</button></li>
-				</ul><!--// tab button -->
-				<!-- 최근 전송내역 -->
-				<div class="history_cont hascont current">
-					<div class="histroy_trans latestMsgArea" id="latestMsgArea">
-						<ul id="latestMsgUl">
-							<c:choose>
-								<c:when test="${not empty resultLatestMsgList}">
-									<c:forEach var="latestMsgList" items="${resultLatestMsgList}" varStatus="status">
-										<li id="latestLi">
-											<input type="checkbox" id="addrChk_${status.count}" name="latAddrChk" value="<c:out value='${latestMsgList.callTo}'/>">
-											<label for="addrChk_${status.count}" class="label">최근 전송내역</label>
-											<p><c:out value="${latestMsgList.callTo}"/></p>
-											<button type="button" id="latestAddrDel"><img src="/publish/images/popup/close3.png"  alt="전화번호 삭제"></button>
-										</li>
-									</c:forEach>
-								</c:when>
-								<c:otherwise>
-									<li>
-										<p>최근 발송 내역이 없습니다.</p>
+	<div class="popup-com history_layer popup03" tabindex="0" data-tooltip-con="popup03" data-focus="popup03" data-focus-prev="popup03-close">
+		<div class="popup_heading">
+			<p><span>전송내역</p>
+			<button type="button" class="tooltip-close" data-focus="popup03-close" id="btnLatestAddPhoneClose"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button>
+		</div>
+		<div class="layer_in">
+			<!-- tab button -->
+			<ul class="tabType6"> 
+				<li class="tab active"><button type="button" onclick="TabType(this,'1');">최근 전송내역</button></li>
+				<li class="tab"><button type="button" onclick="TabType(this,'2');">자주보내는 번호</button></li>
+			</ul><!--// tab button -->
+			<!-- 최근 전송내역 -->
+			<div class="history_cont hascont current">
+				<div class="histroy_trans latestMsgArea" id="latestMsgArea">
+					<ul id="latestMsgUl">
+						<c:choose>
+							<c:when test="${not empty resultLatestMsgList}">
+								<c:forEach var="latestMsgList" items="${resultLatestMsgList}" varStatus="status">
+									<li id="latestLi">
+										<input type="checkbox" id="addrChk_${status.count}" name="latAddrChk" value="<c:out value='${latestMsgList.callTo}'/>">
+										<label for="addrChk_${status.count}" class="label">최근 전송내역</label>
+										<p><c:out value="${latestMsgList.callTo}"/></p>
+										<button type="button" id="latestAddrDel"><img src="/publish/images/popup/close3.png"  alt="전화번호 삭제"></button>
 									</li>
-								</c:otherwise>
-							</c:choose>
-						</ul>
-					</div>
-					<div class="popup_btn_wrap2 hisroy_btn">
-						<button type="button" id="latestAddPhone">선택추가</button>
-						<button type="button" id="latestCancelPhone">선택취소</button>                      
-					</div>
-				</div><!--// 최근 전송내역 -->
-				<!-- 자주보내는 번호 -->
-				<div class="history_cont hascont">
-					<div class="histroy_trans" id="bookMarkMsgArea">
-						<ul id="bookMsgUl">
-							<c:choose>
-								<c:when test="${not empty resultBookMarkMsgList}">
-									<c:forEach var="bookMarkMsgList" items="${resultBookMarkMsgList}" varStatus="status">
-										<li id="bookMarkLi">
-											<input type="checkbox" id="bokAddrChk_${status.count}" name="bookAddrChk" value="<c:out value='${bookMarkMsgList.addrPhoneNo}'/>">
-											<label for="addrChk_${status.count}" class="label">최근 전송내역</label>
-											<p><c:out value="${bookMarkMsgList.addrPhoneNo}"/></p>
-											<button type="button" id="bookMarkAddrDel"><img src="/publish/images/popup/close3.png"  alt="전화번호 삭제"></button>
-										</li>
-									</c:forEach>
-								</c:when>
-								<c:otherwise>
-									<li>
-										<p>등록된 자주 보내는 번호 내역이 없습니다.</p>
+								</c:forEach>
+							</c:when>
+							<c:otherwise>
+								<li>
+									<p>최근 발송 내역이 없습니다.</p>
+								</li>
+							</c:otherwise>
+						</c:choose>
+					</ul>
+				</div>
+				<div class="popup_btn_wrap2 hisroy_btn">
+					<button type="button" id="latestAddPhone">선택추가</button>
+					<button type="button" id="latestCancelPhone">선택취소</button>                      
+				</div>
+			</div><!--// 최근 전송내역 -->
+			<!-- 자주보내는 번호 -->
+			<div class="history_cont hascont">
+				<div class="histroy_trans" id="bookMarkMsgArea">
+					<ul id="bookMsgUl">
+						<c:choose>
+							<c:when test="${not empty resultBookMarkMsgList}">
+								<c:forEach var="bookMarkMsgList" items="${resultBookMarkMsgList}" varStatus="status">
+									<li id="bookMarkLi">
+										<input type="checkbox" id="bokAddrChk_${status.count}" name="bookAddrChk" value="<c:out value='${bookMarkMsgList.addrPhoneNo}'/>">
+										<label for="addrChk_${status.count}" class="label">최근 전송내역</label>
+										<p><c:out value="${bookMarkMsgList.addrPhoneNo}"/></p>
+										<button type="button" id="bookMarkAddrDel"><img src="/publish/images/popup/close3.png"  alt="전화번호 삭제"></button>
 									</li>
-								</c:otherwise>
-							</c:choose>
-						</ul> 
-					</div>
-					<div class="popup_btn_wrap2 hisroy_btn">
-						<button type="button" id="bookMarkAddPhone">선택추가</button>
-						<button type="button" id="bookMarkCancelPhone">선택취소</button>                      
-					</div>
-				</div><!--// 자주보내는 번호  -->         
-			</div>
+								</c:forEach>
+							</c:when>
+							<c:otherwise>
+								<li>
+									<p>등록된 자주 보내는 번호 내역이 없습니다.</p>
+								</li>
+							</c:otherwise>
+						</c:choose>
+					</ul> 
+				</div>
+				<div class="popup_btn_wrap2 hisroy_btn">
+					<button type="button" id="bookMarkAddPhone">선택추가</button>
+					<button type="button" id="bookMarkCancelPhone">선택취소</button>                      
+				</div>
+			</div><!--// 자주보내는 번호  -->         
 		</div>
 	</div>
+</div>
 <!--// 전송내역 팝업 -->
 
-
-
 <!-- 팩스 전송 결과 -->
-
-	<div class="tooltip-wrap">
-		<!-- 문자발송 성공 레이어팝업 -->
-		<div class="popup-com pop_msg_success">
-			<div class="popup_heading">
-				<p>문자 전송 결과</p>
-<!-- 				<button type="button" class="tooltip-close" onclick="msgSuccessClose(this);"><img src="/publish/images/content/layerPopup_close.png" alt="팝업 닫기"></button> -->
-			</div>
-			<div class="layer_in">
-				<div class="msg_text"
-				</div>
-			</div>
-			<div class="popup_btn">
-				<button type="button" onclick="goPage(); return false;">팩스 발송결과 바로가기</button>                      
-				<button type="button" class="tooltip-close" onclick="window.location.reload()">확인</button>                      
+<div class="tooltip-wrap">
+	<!-- 문자발송 성공 레이어팝업 -->
+	<div class="popup-com pop_msg_success">
+		<div class="popup_heading">
+			<p>문자 전송 결과</p>
+		</div>
+		<div class="layer_in">
+			<div class="msg_text"
 			</div>
 		</div>
+		<div class="popup_btn">
+			<button type="button" onclick="goPage(); return false;">팩스 발송결과 바로가기</button>                      
+			<button type="button" class="tooltip-close" onclick="window.location.reload()">확인</button>                      
+		</div>
 	</div>
-
-
+</div>
 <!-- //팩스 전송 결과 -->
 <%--
 ====================================================================
 =								레이어 팝엽 끝						   =
 ====================================================================
- --%>
- 
- 
+ --%>
(No newline at end of file)
src/main/webapp/WEB-INF/jsp/web/msgcampain/include/msgDataIncludeExcel.jsp
--- src/main/webapp/WEB-INF/jsp/web/msgcampain/include/msgDataIncludeExcel.jsp
+++ src/main/webapp/WEB-INF/jsp/web/msgcampain/include/msgDataIncludeExcel.jsp
@@ -559,9 +559,6 @@
 	if(errorCount > 0){
 		alert('휴대폰 형식에 맞지 않는 데이터는 삭제 후 업로드 됩니다.\nex) 발송불가 특수문자, 자릿수 오류 등');
 	}
-	
-	
-	
 }
 
 function fn_dupliPopupShow(){
src/main/webapp/js/user/fax/addr.js
--- src/main/webapp/js/user/fax/addr.js
+++ src/main/webapp/js/user/fax/addr.js
@@ -27,23 +27,21 @@
 
 //주소록 그룹정보 불러오기
 function getAddrGroupList() {
- $.ajax({
-     type : "POST",
-     async : false,
-     url : "/web/mjon/addr/addrGroupListAjax.do",
-     data : {},
-     dataType:'json',
-     success : function(data) {
-		//alert(JSON.stringify(data.addrGroupList));
-
-		// Show Html
-		getAddrGroupListShow(data.addrGroupList);
-     },
-     error : function(xhr, status, error) {
-         alert(error);
-         return false;
-     }
- });	    	
+	$.ajax({
+		type : "POST"
+		, async : false
+		, url : "/web/mjon/addr/addrGroupListAjax.do"
+		, data : {}
+		, dataType:'json'
+		, success : function(data) {
+			// Show Html
+			getAddrGroupListShow(data.addrGroupList);
+		}
+		, error : function(xhr, status, error) {
+			alert(error);
+			return false;
+		}
+	});
 }
 
 //Show Html
@@ -55,7 +53,6 @@
 	for (var j = 0; j < jsonList.length; j++) {
 		sHtml += "	<option value='" + $.trim(jsonList[j].addrGrpId) + "' />" + $.trim(jsonList[j].addrGrpNm) + "</option>";
 	}
-	    	
 	$("#addrGrpIdInfo").html(sHtml);
 }
 
@@ -88,130 +85,55 @@
 	return isReturn;	
 }
 
-//주소록 팝업 닫기 기능
-function addrClose(){
-	
-	$(".closeAddr").trigger("click");
-	
-	//주소록 레이어 팝업의 Tabulator 데이터 지워주기
-	tableAddr.clearData();
-	
-}
-
 //주소록 불러오기에서 수신자 리스트 추가해 주기
-function addrToList(){
+function addrToList_advc(type){
 	
-	var selectedData = tableAddr.getSelectedRows();
+	var tableSize = tableAddr.getDataCount();
 	var tableData = [];
 	
-	if(selectedData == "" || selectedData == null){
-		
+	if(tableSize < 1){
 		alert("주소록을 선택해 주세요.");
 		return false;
-	
-	}else{ // 선택한 Row 데이터 저장해주기
+	}else{
 		
-
-		// fax 번호 유효성 검사
-		for(var i=0; i < selectedData.length; i++){
+		// 선택한 Row 데이터 저장해주기
+		var existingData = tableL.getData();
+		var addrData;
 		
-			var faxNum = removeDash(selectedData[i].getData().addrPhone);
-			if(!checkFaxNum(faxNum)){
-				alert("팩스 번호를 확인해 주세요.");
-				return false;
-				
-			}
+		if(type == 'all'){
+			addrData = tableAddr.getData();
+		}else{
+			addrData = tableAddr.getSelectedData();
 		}
 		
+		// 기존 데이터와 새로운 데이터를 합칩니다.
+		var combinedData = existingData.concat(addrData);
+		// 합쳐진 데이터를 tableL에 설정합니다.
+		tableL.setData(combinedData);
 		
-		for(var i=0; i < selectedData.length; i++){
-			
-			//좌측 받는사람 리스트를 담아둔 배열에 데이터를 추가해 준다.
-			tableData.push({
-				phone: removeDash(selectedData[i].getData().addrPhone), 
-				name: selectedData[i].getData().addrName
-			});
-		}
-	
-		//선택한 데이터 받는사람 리스트에 추가해 주기
-		addPhoneInfo(tableData);
+		var totRows = 0; // 좌측 받는사람 총 갯수
+		totRows = tableL.getRows().length;
+		updateTotCnt(totRows); //전체 데이터 갯수 구하기
 		$(".closeAddr").trigger("click");
 		
 		//주소록 레이어 팝업의 Tabulator 데이터 지워주기
 		tableAddr.clearData();
-
 	}
-	
 }
 
-function loadAddrList(){
-
-	/*
-		serialize 를 사용할때는 processData, contentType 옵션 제가할것
-	*/
-	var data = $("#searchAddrGrpForm").serialize();	 
-
-	var url = "/web/mjon/fax/addr/selectFaxAddrListAjax.do";
-//	var url = "/web/mjon/msgdata/selectMsgAddrListAjax.do";
-	
-	$.ajax({
-        type: "POST", 
-        url: url,
-        data: data,
-        dataType:'json',
-        async: false,
-        cache: false,
-        success: function (returnData, status) {
-        	console.log('returnData :: ', returnData);
-        	console.log('status :: ', status);
-			if(status == 'success'){ // status 확인 필요한가. 석세스 안뜨면 에러 가지 않나
-				
-				if(returnData.result == "success"){
-					
-					var addrList = returnData.resultAddrList;
-					var tableData = [];
-					
-					if(addrList.length == 0){
-						
-						alert("주소록 정보가 없습니다.");
-						tableAddr.setData(tableData);
-						return false;
-					}
-					
-					//받는사람 리스트를 담아둔 배열에 신규 추가 데이터를 추가해 준다.
-					for(var i=0; i < addrList.length; i++){
-						
-						tableData.push({addrGroupNm: addrList[i].addrGrpNm, addrPhone: removeDash(addrList[i].addrPhoneNo) , addrName: addrList[i].addrNm});
-						
-					}
-					
-					//우측 주소록 리스트 Tabulator에 입력해주기
-					tableAddr.setData(tableData);
-					
-				}else{
-					
-					alert(returnData.message);
-					return false;
-					
-				}
-				
-			} else if(status== 'fail'){
-				alert("주소록 불러오기에 실패하였습니다. !!");
-			}
-		},
-        error: function (e) { alert("주소록 불러오기에 실패하였습니다."); console.log("ERROR : ", e); }
-    });
-	
+//주소록 팝업 닫기 기능
+function addrToList_close(){
+	$(".closeAddr").trigger("click");
+	//주소록 레이어 팝업의 Tabulator 데이터 지워주기
+	tableAddr.clearData();
 }
 
+//주소록 검색 기능처리
 function fnAddrSearch(){
-	
 	var form = document.searchAddrGrpForm;
 	form.searchKeyword.value = form.searchAddrKeyword.value;
 	form.searchCondition.value = form.searchAddrCondition.value;
-	
 	loadAddrList();
-	
 }
 
 //주소록 불러오기 팝업의 그룹 선택시 우측에 주소록 불러오기
@@ -232,23 +154,63 @@
 	//왼쪽 그룹리스트의 그룸명을 선택시 검색어를 초기화해준다.
 	form.searchAddrKeyword.value="";
 	
-	/*
-	$(item).toggleClass("open");
-	if ($(item).hasClass("open") === true) {
-		$(item).find("img").attr("src", "/publish/images/content/open_folder2.png");
-		$(item).find("img").attr("alt", "폴더 열림");
-	}
-	else {
-		$(item).find("img").attr("src", "/publish/images/content/close_folder2.png");
-		$(item).find("img").attr("alt", "폴더 닫힘");
-	}
-	*/
-	   
 	$(item).find("img").attr("src", "/publish/images/content/open_folder2.png");
 	$(item).find("img").attr("alt", "폴더 열림");
 	
 	loadAddrList();
+}
+
+//주소록 목록 조회
+function loadAddrList(){
+
+	/*
+		serialize 를 사용할때는 processData, contentType 옵션 제가할것
+	*/
+	var data = $("#searchAddrGrpForm").serialize();	 
+	var url = "/web/mjon/fax/addr/selectFaxAddrListAjax.do";
 	
+	$.ajax({
+        type: "POST", 
+        url: url,
+        data: data,
+        dataType:'json',
+        async: false,
+        cache: false,
+        success: function (returnData, status) {
+        	console.log('returnData :: ', returnData);
+        	console.log('status :: ', status);
+			if(status == 'success'){ // status 확인 필요한가. 석세스 안뜨면 에러 가지 않나
+				
+				if(returnData.result == "success"){
+					
+					var addrList = returnData.resultAddrList;
+					var tableData = [];
+					
+					if(addrList.length == 0){
+						alert("주소록 정보가 없습니다.");
+						tableAddr.setData(tableData);
+						return false;
+					}
+					
+					//받는사람 리스트를 담아둔 배열에 신규 추가 데이터를 추가해 준다.
+					for(var i=0; i < addrList.length; i++){
+						tableData.push({groupNm: addrList[i].addrGrpNm, phone: removeDash(addrList[i].addrPhoneNo) , name: addrList[i].addrNm});
+					}
+					
+					//우측 주소록 리스트 Tabulator에 입력해주기
+					tableAddr.setData(tableData);
+					
+				}else{
+					alert(returnData.message);
+					return false;
+				}
+				
+			} else if(status== 'fail'){
+				alert("주소록 불러오기에 실패하였습니다. !!");
+			}
+		},
+        error: function (e) { alert("주소록 불러오기에 실패하였습니다."); console.log("ERROR : ", e); }
+    });
 }
 
 //주소록 불러오기 그룹명 검색 기능처리
 
src/main/webapp/js/user/fax/exelUpload.js (added)
+++ src/main/webapp/js/user/fax/exelUpload.js
@@ -0,0 +1,420 @@
+$(document).ready(function(){
+	//#############################################################################################
+	//파일업로드 드래그앤 드롭 시작
+	//#############################################################################################
+	
+	var objDragAndDrop = $(".exel_upload_area");
+	$(document).on("dragenter",".exel_upload_area",function(e){
+		e.stopPropagation();
+		e.preventDefault();
+	});
+	$(document).on("dragover",".exel_upload_area",function(e){
+		e.stopPropagation();
+		e.preventDefault();
+	});
+	$(document).on("drop",".exel_upload_area",function(e){
+		fn_excelLoadAddActive();
+		e.preventDefault();
+		var files = e.originalEvent.dataTransfer.files;
+		excelFileChange(files[0]);
+	});
+	
+	$(document).on('dragenter', function (e){
+		e.stopPropagation();
+		e.preventDefault();
+	});
+	$(document).on('dragover', function (e){
+		e.stopPropagation();
+		e.preventDefault();
+	});
+	$(document).on('drop', function (e){
+		e.stopPropagation();
+		e.preventDefault();
+	});
+	//#############################################################################################
+	//파일업로드 드래그앤 드롭 종료
+	//#############################################################################################
+
+	//받는사람 전체삭제 버튼 처리
+	$('#allDel').click(function(){
+		var data = tableExcel.getRows();	
+		tableExcel.clearData();
+		$("#excelRowTotCnt").text(0); //총건수 수정
+		$("#excelRowDupCnt").text(0); //중복건수 수정
+		dupliPhoneDataRealList.length = 0;	// 중복 휴대폰번호 초기화
+		
+		// select box 초기화
+		$('.field-selector').each(function() { $(this).val(''); });
+		
+	});
+
+	//받는사람 선택삭제 버튼 처리해주기
+	$('#in_select_del').click(function(){
+		
+		if(tableExcel == null || tableExcel == ""){
+			alert("받는사람을 추가해 주세요.");
+			return false;
+		}
+		
+		var selectedData = tableExcel.getSelectedRows();
+		
+		if(selectedData == "" || selectedData == null){
+			alert("삭제할 연락처를 선택해주세요.");
+			return false;
+		}else{ // 선택한 Row 데이터 삭제하기
+			if(confirm("선택하신 받는 사람을 삭제하시겠습니까?")){
+				// 선택 데이터 삭제
+			    selectedData.forEach(row => row.delete());
+				totRows = tableExcel.getRows().length;
+			    $("#excelRowTotCnt").text(totRows);
+			}
+		}
+	});
+	
+	$("#excelFile").on("change", function(event) {
+		var fileInfo =  event.target.files;
+		if(fileInfo.length > 0){
+			excelFileChange(fileInfo[0]);
+		} else {
+			fn_excelLoadRemoveActive(); // 파일이 선택되지 않은 경우 로딩 상태 제거
+			setTimeout(() => { $(this).val(''); }, 0);  // 파일 선택 초기화
+		}
+	});
+	
+	//타이틀 select 선택 이벤트
+	 $('.field-selector').on('change', function() {
+		 fn_excelLoadAddActive();
+
+		setTimeout(() => { 
+			var selectedFields = [];
+			var isDuplicate = false;
+	
+			if(tableExcel.getData().length < 1){
+				alert('데이터 입력 후 선택해 주세요.');
+				$(this).val(""); 
+				fn_excelLoadRemoveActive();
+				return false;
+			}
+			
+			// 중복체크
+			$('.field-selector').each(function() {
+				var selectedField = $(this).val();
+				if (selectedField) {
+					if (selectedFields.includes(selectedField)) {
+						alert("중복된 필드를 선택할 수 없습니다.");
+						$(this).val(""); // 중복 필드를 선택한 경우 빈 값으로 초기화
+						isDuplicate = true;
+						return false; // 반복문 종료
+					}
+					selectedFields.push(selectedField);
+				}
+			});
+			
+			updateTableFields(tableExcel);
+			
+			// 필드가 휴대폰이면 열 중복체크
+			if($(this).val() == 'addrFaxNo'){
+				fn_faxDupl(tableExcel);
+			}
+			
+			fn_excelLoadRemoveActive();
+
+		}, 0); // 지연 없이 즉시 실행되도록 0ms 지연을 설정
+		
+	});
+	
+	// 추가버튼
+	$('#btnAddrMassReg').click(function(){
+		
+		if(tableExcel.getData().length < 1){
+			alert("한 개 이상의 연락처를 입력하세요");
+			return false;
+		}
+		
+		// tableExcel 그룹의 select 요소들을 확인
+		var columns = tableExcel.getColumns();
+		var isAddrFaxNoSelected = columns.some(column => column.getField() === 'addrFaxNo');
+
+		if (!isAddrFaxNoSelected) {
+			alert('팩스번호가 선택되지 않았습니다.');
+			return false;
+		} 
+		
+		var addrData = tableExcel.getData().map((row, index) => ({
+		    name: row.addrNm
+		    , phone: removeDash(row.addrFaxNo)
+		}));
+
+		// 기존 tableL의 데이터를 가져옵니다.
+		var existingData = tableL.getData();
+		// 기존 데이터와 새로운 데이터를 합칩니다.
+		var combinedData = existingData.concat(addrData);
+		// 합쳐진 데이터를 tableL에 설정합니다.
+		tableL.setData(combinedData);
+		
+		var totRows = 0; // 좌측 받는사람 총 갯수
+		totRows = tableL.getRows().length;
+		updateTotCnt(totRows); //전체 데이터 갯수 구하기
+		
+		setAddrMassClose();
+		$('.field-selector').each(function() { $(this).val(''); });
+		$('#closeBtn').click();
+	});
+	
+	// 닫기버튼
+	$('#closeBtn').click(function(){
+		setAddrMassClose();
+	});
+	
+	// 닫기버튼
+	$('#btnAddrMassClose').click(function(){
+		setAddrMassClose();
+	});
+	
+	// excel 오류정보 테스트
+	$(document).on('click', '#errorExcelBtn', function() {
+		if(tableError.getDataCount()<1){
+			alert('오류 정보가 없습니다.');
+			return false;
+		}
+		tableError.download("xlsx", "error_data.xlsx");
+	});
+});
+//팝업 텍스트 더보기 클릭 시 펼쳐지고 숨겨짐
+function popMore(e){
+	$(e).closest(".pop_more_cont").toggleClass("pop_more_click");
+	
+	if($(e).closest(".pop_more_cont").is(".pop_more_click")){
+		$(e).html('숨기기');
+		$(e).append('<i></i>');
+	}else {
+		$(e).html('더보기');
+		$(e).append('<i></i>');
+	}
+}
+
+//엑셀등록 초기화 값 설정
+function setAddrMassClose() {
+	tableExcel.clearData();
+	$("#excelRowTotCnt").text(0);		//총건수 수정
+	$("#excelRowDupCnt").text(0);		//중복건수 수정
+	$("#excelRowErrorCnt").text(0);		//중복건수 수정
+	dupliPhoneDataRealList.length = 0;	// 중복 휴대폰번호 초기화
+	addrMassDupliSaveList = null;
+	
+	$('#excelFile').val(''); //첨부파일 값 초기화
+	
+	// popup 영역
+	tableError.clearData();
+	$("#errorPopDupCnt").text(0);	// 중복 카운트
+	$("#errorPopErrorCnt").text(0); // 에러 카운트
+	$("#errorPopTotCnt").text(0);
+	$('.field-selector').each(function() { $(this).val(''); }); //select 선택란 초기화
+}
+
+//엑셀파일 업로드
+function excelFileChange(file) {
+	if (file) {
+		// 파일 크기 체크 (20MB)
+		const maxSize = 20 * 1024 * 1024; // 20MB in bytes
+		if (file.size > maxSize) {
+			alert('파일 크기는 20MB를 초과할 수 없습니다.');
+			return;
+		}
+		
+		fn_excelLoadAddActive();
+		var reader = new FileReader();
+		var extension = file.name.split('.').pop().toLowerCase();
+		reader.onload = function(e) {
+			setTimeout(() => { // 파일 읽기 완료 후 실행되도록 함
+				if (extension === 'xlsx') {
+					var data = new Uint8Array(e.target.result);
+					var workbook = XLSX.read(data, {type: 'array'});
+					var firstSheet = workbook.Sheets[workbook.SheetNames[0]];
+					var jsonData = XLSX.utils.sheet_to_json(firstSheet, {header: 1});
+					processExcelData(jsonData);
+				} else {
+					alert('지원되지 않는 파일 형식입니다.');
+				}
+				fn_excelLoadRemoveActive();
+			}, 0); // 지연 없이 즉시 실행되도록 0ms 지연을 설정
+		};
+		if (extension === 'xlsx') {
+			reader.readAsArrayBuffer(file);
+		} 
+	}
+}
+
+//엑셀 데이터 처리 함수
+function processExcelData(data) {
+	var keys = ['A', 'B'];
+	var tableData = [];
+	
+	data.slice(0).forEach((row, index) => {
+		var rowData = {};
+		keys.forEach((key, idx) => { // index 변수명 변경 (내부와 외부에서 사용되므로 충돌 방지)
+			rowData[key] = (typeof row[idx] === 'string') ? row[idx].trim() : row[idx];
+		});
+		
+		tableData.push(rowData);
+	});
+	
+	updateTable(tableData);
+}
+
+//공통 테이블 업데이트 함수
+function updateTable(tableData) {
+	tableExcel.setColumns([ //Define Table Columns
+ 		{formatter:"rowSelection", titleFormatter:"rowSelection",clipboard:false, headerHozAlign:"center", hozAlign:"center", width:10, headerSort:false, cellClick:function(e, cell){
+ 	        cell.getRow().toggleSelect();
+			}
+	 	}
+ 		,{formatter:"rownum", align:"center" ,title:"No", hozAlign:"center", headerHozAlign:"center", width:100}
+ 		,{title:"A", field:"A", hozAlign:"center", headerHozAlign: "center", width:400, validator:["maxLength:100", "string"]}
+ 		,{title:"B", field:"B", hozAlign:"center", headerHozAlign: "center", width:400, validator:["maxLength:100", "string"]}
+ 	]);
+
+	// excelRowTotCnt 업데이트
+	tableExcel.setData(tableData).then(() => {
+		document.getElementById("excelRowTotCnt").innerText = tableData.length;
+	});
+	
+	fn_excelLoadRemoveActive();
+}
+
+
+/* 
+* 타이틀 select 선택할때마다 실행해서         
+* 데이터테이블 필드값 수정                  
+*/
+function updateTableFields(objTabul) {
+	var currentData = objTabul.getData();
+	var columns = [
+		{formatter: "rowSelection", titleFormatter: "rowSelection", clipboard: false, hozAlign: "center", headerHozAlign: "center", width:10, headerSort: false, cellClick: function(e, cell) {
+			cell.getRow().toggleSelect();
+		}}
+		,{formatter:"rownum", align:"center", title:"No", hozAlign:"center", headerHozAlign:"center", width:100}
+	];
+
+	var fieldMapping = [];
+	$('.field-selector').each(function(index) {
+		var selectedField = $(this).val();
+		var field = String.fromCharCode(65 + index);
+		if (selectedField) {
+			columns.push({
+				title: field
+				, field: selectedField
+				, hozAlign: "center"
+				, headerHozAlign: "center"
+				, editor: false
+				, width: 400
+				, validator: ["maxLength:100", "string"]
+			});
+			fieldMapping.push(selectedField);
+		} else {
+			columns.push({
+				title: field
+				, field: field
+				, hozAlign: "center"
+				, headerHozAlign: "center"
+				, editor: false
+				, width: 400
+				, validator: ["maxLength:100", "string"]
+			});
+			fieldMapping.push(field);
+		}
+	});
+
+	var updatedData = currentData.map(row => {
+		var newRow = {};
+		fieldMapping.forEach((field, index) => {
+			newRow[field] = row[Object.keys(row)[index]] || "";
+		});
+		return newRow;
+	});
+
+	objTabul.setColumns(columns);
+	objTabul.setData(updatedData);
+}
+
+/**
+ * @ 팩스번호 중복 데이터
+ * */
+function fn_faxDupl(objTabul) {
+	 
+	tableError.clearData();
+	
+	var data = objTabul.getData();
+	var phoneNumberChk = false;
+	var existingNumbers = new Set(); // 배열에서 Set으로 변경
+	
+	let errorCount = 0; // 중복 번호 개수를 저장할 변수
+	let duplicateCount = 0; // 중복 번호 개수를 저장할 변수
+	
+	const errors = [];  // 오류 데이터를 저장할 배열
+	const newData = []; // 유효한 데이터만 저장할 새로운 배열
+	
+	data.forEach((row, index) => {
+		
+		const number = row.addrFaxNo;
+		
+		// number가 null, undefined, 빈 문자열이거나 숫자인 경우 처리
+		if (!number || (typeof number === 'string' && !number.trim())){
+			console.log("number : ", number);
+			 return;
+		}
+		
+		const formattedNumber = formatPhoneNumber(number); // 번호 표준화
+		const cleanedNumber = formattedNumber.replace(/[^0-9]/g, ''); // 숫자만 남김
+		
+		if (!existingNumbers.has(cleanedNumber)) {		// 중복 번호 체크
+		    if (checkFaxNum(formattedNumber)) {			// 유효성 검사
+		        row.addrFaxNo = formattedNumber;
+		        existingNumbers.add(cleanedNumber);		// 추가된 번호를 기존 목록에 추가
+		        newData.push(row);						// 유효한 데이터만 새로운 배열에 추가
+		    } else {
+				// 오류: 유효성 통과 못함
+				errorCount++;
+				errors.push({
+					name: row.addrNm			// 이름
+					, phone: row.addrFaxNo		// 팩스번호
+					, result: "오류"				// 결과 메시지 추가
+				});
+		    }
+		} else {
+			// 중복
+			duplicateCount++;
+			errors.push({
+				name: row.addrNm			// 이름
+				, phone: row.addrFaxNo		// 팩스번호
+				, result: "오류"				// 결과 메시지 추가
+			});
+		}
+	});
+	
+	// data 배열을 newData 배열로 대체
+	data = newData;
+	
+
+	// 수정된 데이터로 테이블 업데이트
+	objTabul.setData(data);
+	// 오류 총 카운트
+    $("#excelRowTotCnt").text(objTabul.getDataCount());
+	// 중복 카운트
+	$("#excelRowDupCnt").text(duplicateCount);
+	// 에러 카운트
+	$("#excelRowErrorCnt").text(errorCount);
+	
+	// popup 영역
+	$("#errorPopTotCnt").text(objTabul.getDataCount());
+	// 중복 카운트
+	$("#errorPopDupCnt").text(duplicateCount);
+	// 에러 카운트
+	$("#errorPopErrorCnt").text(errorCount);
+	
+	tableError.setData(errors);
+	
+	if(errorCount > 0){
+		alert('휴대폰 형식에 맞지 않는 데이터는 삭제 후 업로드 됩니다.\nex) 발송불가 특수문자, 자릿수 오류 등');
+	}
+}
src/main/webapp/js/user/fax/tabulator.js
--- src/main/webapp/js/user/fax/tabulator.js
+++ src/main/webapp/js/user/fax/tabulator.js
@@ -1,23 +1,27 @@
 
 $(document).ready(function (){
 	
-	//받는사람 연락처 내용 처리
-	//Tabulator AJAX Data Loading
+	//받는사람 연락처 Tabulator 설정
 	tableL = new Tabulator(".callList_box", {
 		height:"255px",
-		layout:"fitDataStretch",
+		layout:"fitColumns",
 	    headerHozAlign:"center",
 	    validationMode:"highlight",
 	    placeholder:"복사(Ctrl+C)한 내용을 여기에 붙여넣기(Ctrl+V) 해주세요.", //fit columns to width of table (optional)
 	    resizableColumns:false,
+	    columnDefaults:{ // 공통설정
+	        hozAlign: "center",
+	        headerHozAlign: "center",
+	        editor: "input",
+	        editor: false
+	    },
 	 	columns:[ //Define Table Columns
-	 		{formatter:"rowSelection", titleFormatter:"rowSelection",clipboard:false, hozAlign:"center", headerSort:false, cellClick:function(e, cell){
+	 		{formatter:"rowSelection", titleFormatter:"rowSelection",clipboard:false, hozAlign:"center", width:5, headerSort:false, cellClick:function(e, cell){
 	 	        cell.getRow().toggleSelect();
 		 	}}, 
-		 	{title:"이름", hozAlign:"center", field:"name", editor:"input", validator:["maxLength:12"], cellEdited:function(cell){
-		    }},
-		 	{title:"수신번호", hozAlign:"center", field:"phone", editor:"input", width:100, validator:["required","minLength:10", "maxLength:12", "regex:/[^0-9]/g, ''"], cellEdited:function(cell){
-		 	    //cell - cell component
+		 	{title:"No", formatter:"rownum", align:"center", hozAlign:"center", width:60},
+		 	{title:"이름", field:"name", validator:["maxLength:12"]},
+		 	{title:"수신번호", field:"phone", validator:["required","minLength:10", "maxLength:12", "regex:/[^0-9]/g, ''"], cellEdited:function(cell){
 		 	    fnDuplPhone();
 		    }},
 	 	],
@@ -51,29 +55,23 @@
 
 	});
 	
-	
-	//주소록 불러오기 팝업 내용
-	//Tabulator AJAX Data Loading
+	//주소록 불러오기 팝업 Tabulator 설정
 	tableAddr = new Tabulator(".callAddr_box", {
 		height:"255px",
 	    layout:"fitColumns",
 	    headerHozAlign:"center",
 	    validationMode:"highlight",
-	    placeholder:"주소록 그룹을 선택해 주세요.", //fit columns to width of table (optional)
+	    placeholder:"주소록 그룹을 선택해 주세요.",
 	    resizableColumns:false,
+	    progressiveLoad:"scroll",
 	 	columns:[ //Define Table Columns
-	 		{formatter:"rowSelection", titleFormatter:"rowSelection",clipboard:false, hozAlign:"center", headerSort:false, cellClick:function(e, cell){
+	 		{formatter:"rowSelection", headerHozAlign:"center", titleFormatter:"rowSelection",clipboard:false, hozAlign:"center", width:10, headerSort:false, cellClick:function(e, cell){
 	 	        cell.getRow().toggleSelect();
-		 		}
-		 	}, 
-		 	{title:"그룹명", hozAlign:"center", field:"addrGroupNm", editor:"input", width:200, validator:["required","minLength:2", "maxLength:40"]},
-		 	{title:"이름", hozAlign:"center", field:"addrName", editor:"input",  width:250, validator:["maxLength:12"]},
-		 	{title:"수신자번호", hozAlign:"center", field:"addrPhone", editor:"input", width:300, validator:["required","minLength:10", "maxLength:11"]},
-		 	// {title:"[*1*]", hozAlign:"center", field:"addrRep1", editor:"input", width:84, validator:["maxLength:40"]},
-		 	// {title:"[*2*]", hozAlign:"center", field:"addrRep2", editor:"input", width:84, validator:["maxLength:40"]},
-		 	// {title:"[*3*]", hozAlign:"center", field:"addrRep3", editor:"input", width:84, validator:["maxLength:40"]},
-		 	// {title:"[*4*]", hozAlign:"center", field:"addrRep4", editor:"input", width:84, validator:["maxLength:40"]},
-		 	
+	 		}},
+	 		{formatter: "rownum", align: "center", title: "No", hozAlign: "center", headerHozAlign: "center", width: 60},
+		 	{title:"그룹명", hozAlign:"center", field:"groupNm", editor: false, width:200, validator:["required","minLength:2", "maxLength:40"]},
+		 	{title:"이름", hozAlign:"center", field:"name", editor:false,  width:200, validator:["maxLength:12"]},
+		 	{title:"수신자번호", hozAlign:"center", field:"phone", editor:false, width:200, validator:["required","minLength:10", "maxLength:11"]},
 	 	],
 	 	validationFailed:function(cell, value, parameters){ // 유효성 체크 함수 - 아직 잘 모르겠음 
 	 		var valid = cell.isValid();
@@ -94,8 +92,60 @@
 	 		}
 	 		return value % parameters.addrPhone;
 	    },
-
 	});
+	
+	//엑셀 불러오기 팝업 Tabulator 설정
+	tableExcel = new Tabulator("#tabulator_excel", {
+		height:"255px",
+		width:"100%",
+	    layout:"fitColumns",
+	    autoColumns:false,
+	    headerHozAlign:"center", 
+	    validationMode:"highlight",
+	    clipboard:false,
+	    clipboardCopySelector:"table",
+	    clipboardPasteAction:"insert", // insert, update, replace
+	    placeholder:"Excel 파일을 업로드 해주세요.", //fit columns to width of table (optional)
+	 	columns:[ //Define Table Columns
+	 		{formatter:"rowSelection", titleFormatter:"rowSelection",clipboard:false, headerHozAlign:"center", hozAlign:"center", width:10, headerSort:false, cellClick:function(e, cell){
+	 	        cell.getRow().toggleSelect();
+	 		}}
+	 		,{formatter:"rownum", align:"center" ,title:"No", hozAlign:"center", headerHozAlign:"center", width:100}
+	 		,{title:"A", field:"A", hozAlign:"center", headerHozAlign: "center", width:400, validator:["maxLength:100", "string"]}
+	 		,{title:"B", field:"B", hozAlign:"center", headerHozAlign: "center", width:400, validator:["maxLength:100", "string"]}
+	 	],
+	 	validationFailed:function(cell, value, parameters){ // 유효성 체크 함수 
+	        var valid = cell.isValid();
+	 		if(!valid){
+	 			alert("양식에 맞지 않는 정보가 입력되었습니다.");
+	 			
+	 			//해당 셀 데이터 삭제
+	 			cell.setValue("");
+	 		}
+	 		return value % parameters.phone;
+	    },
+	});
+	
+	//엑셀 오류 주소록 상세  팝업 Tabulator 설정
+	tableError = new Tabulator("#tabulator_error", {
+		height:"255px",
+		width:"100%",
+	    layout:"fitColumns",
+	    autoColumns:false,
+	    headerHozAlign:"center", 
+	    validationMode:"highlight",
+	    clipboard:false,
+	    clipboardCopySelector:"table",
+	    clipboardPasteAction:"insert", // insert, update, replace
+	    placeholder:"등록 팝업에서 휴대폰을 선택 후 확인해주세요.", //fit columns to width of table (optional)
+	 	columns:[ //Define Table Columns
+		 	{title:"이름", field:"name", hozAlign:"center", headerHozAlign: "center", width:125},
+		 	{title:"휴대폰", field:"phone", hozAlign:"center", headerHozAlign: "center", width:158},
+		 	{title:"미등록 결과", field:"result", hozAlign:"center", headerHozAlign: "center", width:125}
+	 	]
+	});
+	
+	
 	
 	//핸드폰 번호 Tabulator에서 수정시 중복 체크
 	function fnDuplPhone(){
@@ -130,9 +180,7 @@
 				updateTotCnt(totRows); //전체 데이터 갯수 구하기
 				
 			}
-			
 		}
-		
 	}
 	
 	//받는사람 목록에 복사/붙여넣기 기능 처리
@@ -324,7 +372,6 @@
 			alert("올바른 팩스 번호를 입력해 주세요.");
 			$('#callTo').focus();
 			return false;
-			
 		}
 		callToNum = callToNum.replaceAll("[^0-9]", "");
 		
@@ -338,11 +385,8 @@
 	    for(var i=0; i < tableL.getRows().length; i++){
 	    	
 	    	if(callToNum == data[i].getData().phone){
-	    		
 	    		dpCnt++;
-	    	
 	    	}
-	    	
 	    }
 	    
 	    if(dpCnt > 0){
@@ -360,9 +404,7 @@
 	    	var totLen = tableL.getRows().length;
 	    	
 	    	for(var i=0; i < totLen; i++){
-		    	
 		    	tableData.push({phone: data[i].getData().phone.trim(), name: data[i].getData().name});
-		    	
 		    }
 			
 	    	//연락처 추가해 주기
@@ -378,9 +420,7 @@
 		    //totalPriceSum(totRows);
 		    
 		    $('#callTo').val("");
-	    
 	    }
-		
 	});
 	
 	
@@ -402,9 +442,7 @@
 				$("#rowDupCnt").text(0); //중복건수 수정
 				totalPriceSum(0);		 //결제 금액 수정
 			}
-	
 		}
-		
 	});
 	
 	
@@ -415,7 +453,6 @@
 			
 			alert("받는사람을 추가해 주세요.");
 			return false;
-		
 		}
 		
 		var selectedData = tableL.getSelectedRows();
@@ -441,23 +478,8 @@
 			    
 				var smsTxtArea = $('#smsTxtArea').val();
 				fn_priceClclt();
-//				//일괄변환 문구 결제금액 처리
-//				if(smsTxtArea.indexOf("[*이름*]") > -1
-//						|| smsTxtArea.indexOf("[*1*]") > -1
-//						|| smsTxtArea.indexOf("[*2*]") > -1
-//						|| smsTxtArea.indexOf("[*3*]") > -1
-//						|| smsTxtArea.indexOf("[*4*]") > -1){
-//					
-//					fnReplCell();
-//				}else{
-//					//결제 금액 구하기
-//				    totalPriceSum(totRows);
-//				}
-				
 			}
-
 		}
-		
 	});
 	
 	//주소록 불러오기 버튼 클릭시
@@ -473,7 +495,6 @@
 		}
 		
 		$("#addrGroupLoad").load("/web/mjon/fax/addr/selectFaxAddrGroupListAjaxView.do", "" ,function(response, status, xhr){
-//		$("#addrGroupLoad").load("/web/mjon/fax/addr/faxAddrGroupListAjax.do", "" ,function(response, status, xhr){
 			//리스트 스크롤 처리해주기
 			$(".adr_pop_list").mCustomScrollbar({
 				axis: 'y',
@@ -507,17 +528,7 @@
 		$("input:checkbox[name='latAddrChk']:checked").each(function(index){
 			
 			var chkPhone = $(this).val();
-			
-			// if(!checkHpNum(chkPhone)){
-				
-			// 	alert("올바른 전화번호가 아닙니다.");
-			// 	return false;
-				
-			// }else{
-				
-				addPhoneList.push({phone: removeDash(chkPhone.trim())});
-				
-			// }
+			addPhoneList.push({phone: removeDash(chkPhone.trim())});			
 			
 		});
 		
@@ -531,34 +542,16 @@
 			alert("연락처를 선택해주세요.");
 			return false;
 		}		
-		
-		//중복연락처 제거
-		//var removeDuplData = dupliPhoneData(addPhoneList);
-		
-		//받는사람 목록에 추가
-		//tableL.addData(removeDuplData);
-	    
-	    //총 받는사람 수 계산
-	    //totRows = tableL.getRows().length;
-	    //updateTotCnt(totRows);
-	    
-	  	//결제 금액 구하기
-	    //totalPriceSum(totRows);
-		
 	});
 	
 	//최근전송내역 팝업 선택 취소 버튼 처리
 	$(document).on('click', '#latestCancelPhone', function (){
-		
 		$("input[name=latAddrChk]").prop("checked", false);
-		
 	});
 	
 	//최근전송내역 팝업 삭제 버튼 처리
 	$(document).on('click', '#latestAddrDel', function (){
-		
 		$(this).parent("#latestLi").remove();
-		
 	});
 	
 	//자주보내는 번호 팝업 선택추가 버튼 처리(체크내역 받는사람 리스트로 추가해주기)
@@ -567,20 +560,8 @@
 		var addPhoneList = []; //신규로 추가할 전화번호 저장변수
 		
 		$("input:checkbox[name='bookAddrChk']:checked").each(function(index){
-			
 			var chkPhone = $(this).val();
-			
-//			if(!checkHpNum(chkPhone)){
-//				
-//				alert("올바른 전화번호가 아닙니다.");
-//				return false;
-//				
-//			}else{
-				
-				addPhoneList.push({phone: removeDash(chkPhone.trim())});
-				
-//			}
-			
+			addPhoneList.push({phone: removeDash(chkPhone.trim())});
 		});
 		
 		if(addPhoneList.length > 0){
@@ -592,20 +573,6 @@
 			alert("연락처를 선택해주세요.");
 			return false;
 		}		
-		
-		//중복연락처 제거
-		//var removeDuplData = dupliPhoneData(addPhoneList);
-		
-		//받는사람 목록에 추가
-		//tableL.addData(removeDuplData);
-	    
-	    //총 받는사람 수 계산
-	    //totRows = tableL.getRows().length;
-	    //updateTotCnt(totRows);
-	    
-	  	//결제 금액 구하기
-	    //totalPriceSum(totRows);
-		
 	});
 	
 	//자주보내는 번호 팝업 선택 취소 버튼 처리
@@ -651,47 +618,31 @@
 				for(var i=0; i < totLen; i++){
 					
 					var cellValue = invalid[i].getValue();
-					
 					if(i == 0){
-						
 						errMsg = cellValue;
-						
 					}else{
-						
 						errMsg = errMsg +", "+ cellValue;
-						
 					}
-					
 				}
 				
 				if(errMsg == "" || errMsg == null){
-					
 					alert("내용에 오류가 있습니다.");
 					return false;
-					
 				}else{
-					
 					alert(errMsg + "의 내용에 오류가 있습니다.");
 					return false;
-					
 				}
 				
 			}else{
-				
 				alert("오류 데이터가 없습니다.");
 				return false;
-				
 			}
 			
 		}else{
-			
 			alert("연락처를 입력해 주세요.");
 			return false;
-			
 		}
-		
 	});
-	
 });
 
 var tableErrorData = [];
@@ -700,19 +651,15 @@
 
 //전체 데이터 갯수 구하는 함수
 function updateTotCnt(data){
-	
 	$("#rowTotCnt").text(data);
-
 }
 
 //주소록 불러오기에서 수신자 리스트 tabulator에 데이터 추가해주기
 function addPhoneInfo(data){
 	
 	if(data == null){
-		
 		alert("연락처 정보가 없습니다.");
 		return;
-		
 	}else{
 		
 		var idx = 0;
@@ -730,9 +677,7 @@
 		
 		//받는사람 리스트를 담아둔 배열에 신규 추가 데이터를 추가해 준다.
 		for(var i=0; i < newData.length; i++){
-			
 			tableData.push({phone: removeDash(newData[i].phone) , name: newData[i].name});
-			
 		}
 		
 		var temp = tableData.length;
@@ -748,24 +693,7 @@
 		
 		var smsTxtArea = $('#smsTxtArea').val();
 		fn_priceClclt();
-		//일괄변환 문구 결제금액 처리
-//		if(smsTxtArea.indexOf("[*이름*]")  > -1 
-//				|| smsTxtArea.indexOf("[*1*]") > -1
-//				|| smsTxtArea.indexOf("[*2*]") > -1
-//				|| smsTxtArea.indexOf("[*3*]") > -1
-//				|| smsTxtArea.indexOf("[*4*]") > -1){
-//			
-//			fnReplCell();
-//			
-//		}else{
-//			
-//			//결제 금액 구하기
-//		    totalPriceSum(totRows);
-//			
-//		}
-		
 	}
-	
 }
 
 
src/main/webapp/publish/css/content.css
--- src/main/webapp/publish/css/content.css
+++ src/main/webapp/publish/css/content.css
@@ -1466,6 +1466,15 @@
 .loading_layer .loading_container .bar {position:absolute;left:0;top:0;width:100%;height:100%;border:6px solid #fff;border-top-color:transparent;border-bottom-color:transparent;border-radius:60px;box-sizing:border-box;animation:rotate-loading 1.5s linear infinite;}
 .loading_layer .loading_container .text {font-size:15px;line-height:108px;text-align:center;color:#fff;animation:text-loading 1s ease-in infinite;}
 
+
+.loading_execl_layer {display:none;position:fixed;left:0;top:0;width:100%;height:100%;z-index:1000000;}
+.loading_execl_layer.active {display:block;}
+.loading_execl_layer:after {content:'';display:block;width:100%;height:100%;background:#000;opacity:0.5;filter:opacity(50);}
+.loading_execl_layer .loading_container {position:absolute;left:50%;top:50%;width:110px;height:110px;transform:translate(-50%,-50%);z-index:1;}
+.loading_execl_layer .loading_container .bar {position:absolute;left:0;top:0;width:100%;height:100%;border:6px solid #fff;border-top-color:transparent;border-bottom-color:transparent;border-radius:60px;box-sizing:border-box;animation:rotate-loading 1.5s linear infinite;}
+.loading_execl_layer .loading_container .text {font-size:15px;line-height:108px;text-align:center;color:#fff;animation:text-loading 1s ease-in infinite;}
+
+
 .upload_area .loading_layer{position: absolute;}
 .upload_area .loading_layer.active+p,.upload_area .loading_layer.active+p+.cf_text_wrap{opacity: 0;}
 
src/main/webapp/publish/css/popupLayer.css
--- src/main/webapp/publish/css/popupLayer.css
+++ src/main/webapp/publish/css/popupLayer.css
@@ -1202,6 +1202,9 @@
 .file_upload_wrap .file_add.upload_area p{display:block;}
 .file_upload_wrap  .btnType.c3{position:unset;height:82px;}
 
+.file_upload_wrap .file_add.exel_upload_area{display:flex;width:78%;margin:0;align-items:center;justify-content:center;}
+.file_upload_wrap .file_add.exel_upload_area p{display:block;}
+
 .adr_layer.adr_popup01 .btn_list_detail {width:23px;height:23px;margin:-3px 0 0 5px;border:1px solid #d5d5d5;border-radius:5px;}
 .adr_layer.adr_popup01 .btn_list_detail img{width:69%;height:auto;margin:-3.5px 0 0 0;}
 .adr_layer.adr_popup14 .table_top{display:flex;align-items:center;justify-content:space-between;}
src/main/webapp/publish/js/content.js
--- src/main/webapp/publish/js/content.js
+++ src/main/webapp/publish/js/content.js
@@ -1571,3 +1571,11 @@
 function fn_loadRemoveActive(){
 	$('.loading_layer').removeClass('active');
 }
+
+function fn_excelLoadAddActive(){
+	$('.loading_execl_layer').addClass('active');
+}
+
+function fn_excelLoadRemoveActive(){
+	$('.loading_execl_layer').removeClass('active');
+}
Add a comment
List