123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708 |
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>노드 일괄등록</title>
- <script type="text/javascript" src="/js/ext/jquery.min.js"></script>
- <script type="text/javascript" src="/js/ext/xlsx.full.min.js"></script>
- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
-
- <style>
- body {
- background-color: rgb(52,55,58);
- padding: 15px;
- margin: 0;
- color: #cccccc;
- font-size: 18px;
- font-weight: bold;
- display: grid;
- grid-template-rows: auto;
- grid-row-gap: 15px;
- }
-
- .batch-popup {
- font-weight: bold;
- display: grid;
- /* grid-template-rows: 60px 30px 210px 1fr; */
- grid-template-rows: 60px 30px 1fr;
- grid-row-gap: 30px;
- padding: 15px;
- background: #777;
- }
-
- .input-file {
- display: grid;
- grid-template-columns: min-content auto;
- border: 2px solid #706f6f;
- background: #ccc;
- height: 60px;
- }
- .input-file .file-label {
- display: grid;
- width: 115px;
- height: 60px;
- line-height: 20px;
- padding: 0 10px;
- border-radius: 2px;
- background-color: #eee;
- color: #706f6f;
- cursor: pointer;
- border-right: 2px solid #706f6f;
- font-size: 14px;
- align-items: center;
- }
- .input-file .upload-file {
- color: #777;
- padding: 5px;
- font-size: 14px;
- display: grid;
- grid-template-rows: 1fr 1fr;
- }
- .input-file .upload-file .upload-button {
- display: grid;
- grid-template-columns: 8fr 1fr;
- }
- .input-file .upload-file .upload-button .validate {
- background: #efefef;
- border: 1px solid #767676;
- text-align: center;
- line-height: 23px;
- font-size: 13px;
- font-weight: 400;
- color: rgb(0 0 0);
- border-radius: 3px;
- }
- .input-file .upload-file .upload-button .validate:hover {
- cursor: pointer;
- }
-
- .input-option {
- display: grid;
- grid-template-columns: min-content auto;
- border: 2px solid #706f6f;
- background: #ccc;
- height: 30px;
- }
- .input-option .option-label {
- display: grid;
- width: 115px;
- height: 30px;
- padding: 0 10px;
- border-radius: 2px;
- background-color: #eee;
- color: #706f6f;
- cursor: pointer;
- border-right: 2px solid #706f6f;
- font-size: 14px;
- align-items: center;
- }
- .input-option .upload-option {
- color: #777;
- padding: 5px;
- font-size: 14px;
- display: grid;
- grid-template-columns: 1fr 1fr;
- }
-
- .button-div {
- /* position: relative; */
- /* top: 45px; */
- height: 55px;
- /* line-height: 58px; */
- border-top: 2px solid rgb(170 170 183);
- display: grid;
- grid-template-columns: 92px 92px;
- justify-content: space-between;
- align-items: end;
- }
-
- .confirm {
- width: 80px;
- color:#706f6f;
- height: 36px;
- line-height: 40px;
- border: 1px solid #eeeeee;
- background: #f7f7f6;;
- text-align: left;
- padding-left: 10px;
- }
-
- .cancel {
- width: 80px;
- color:#706f6f;
- height: 36px;
- line-height: 40px;
- border: 1px solid #eeeeee;
- background: #f7f7f6;;
- text-align: left;
- padding-left: 10px;
- }
-
- .confirm:hover,
- .cancel:hover {
- cursor: pointer;
- background: rgb(0, 120, 215);
- color: white;
- border-color: white;
- }
-
- .inspection-option {
- /* display: grid; */
- display: none;
- grid-template-rows: auto;
- grid-row-gap: 10px;
- }
- .inspection-label {
- color: #ffffff;
- padding: 0 3px;
- height: 30px;
- }
- .inspection-result {
- border: 2px solid #706f6f;
- background: #ccc;
- height: 166px;
- color: #000;
- overflow: auto;
- font-size: 13px;
- font-weight: 400;
- }
- </style>
- </head>
- <body>
- 노드정보 일괄등록
- <div class="batch-popup">
- <div class="input-file">
- <label for="upload01" class="file-label">엑셀 업로드<br>(파일)</label>
- <div class="upload-file">
- *등록하려는 엑셀 파일입니다.
- <div class="upload-button">
- <input type="file" id="upload01" name="upload01" onchange="regionExcel()">
- <div class="validate">
- 검사
- </div>
- </div>
- </div>
- </div>
- <div class="input-option">
- <div class="option-label">업로드 옵션</div>
- <div class="upload-option">
- <div>
- <input type="radio" id="option1" name="option" value="upload1" checked>
- <label for="option1">중복 데이터 제외 후 추가</label>
- </div>
- <div>
- <input type="radio" id="option2" name="option" value="upload2">
- <label for="option2">중복 데이터 수정 및 추가</label>
- </div>
- </div>
- </div>
- <div class="inspection-option">
- <div class="inspection-label">검사 결과</div>
- <div class="inspection-result">
-
- </div>
- </div>
- <div class="button-div">
- <div class="confirm">
- <i class='fa fa-check' style="font-size: 25px;" aria-hidden='true'></i> 등록
- </div>
- <div class="cancel">
- <i class='fa fa-times' style="font-size: 25px;" aria-hidden='true'></i> 취소
- </div>
- </div>
- </div>
- <script>
- let nodeIdData = [];
- allNodeId();
- // 검사 버튼 이벤트
- $(".validate").on('click',()=>{
- if(!addData.length){
- alert("엑셀이 등록되지 않았거나, 엑셀 데이터가 존재하지 않습니다.")
- } else {
- $(".batch-popup")[0].style["grid-template-rows"] = "60px 30px 210px 1fr"
- $(".inspection-option")[0].style["display"] = "grid"
- $(window)[0].resizeTo(616, 620);
- validateExcel($("input[name='option']:checked").val());
- }
- })
-
- // 확인 버튼 이벤트
- $(".confirm").on('click',()=>{
- saveExcel();
- })
-
- // 취소 버튼 이벤트
- $(".cancel").on('click',()=>{
- window.close();
- })
-
- let obj;
-
- let region = [];
-
- // 엑셀 READ result
- let addData = [];
-
- // 예외처리 후 result
- let result = [];
-
- // 예외처리 에러리스트
- let errList = [];
-
- // 에러 메세지
- let message = "";
-
- // 검사 여부
- let validateYN = 0;
-
- // 라디오 버튼
- $("input[name='option']:radio").change(function () {
- validateYN = 0;
- });
-
- // 삭제 항목
- let delStr = ""
-
- // 형식 검사를 위한 정규식
- const latitudePattern = /^([0-9]{1,2})([.]{1})([0-9]{1,14})$/
- const longitudePattern = /^([0-9]{1,3})([.]{1})([0-9]{1,14})$/
- const nodeIdPattern = /^[0-9]{1,10}$/;
- const ntPattern = /^[0-9]*$/;
-
- function regionArr(arr){
- $.ajax({
- url:"/api/getAllRegion.do",
- async:false,
- type: "get",
- dataType: "json",
- success:function(result){
- arr.push(result);
- }, error: function(error) {
- console.log(error)
- }
-
- })
- }
-
- // 지역 코드 정의
- let regionIndex = {
- "서울시" : "L01",
- "인천시" : "L02",
- "부천시" : "L03",
- "광명시" : "L04",
- "안양시" : "L05",
- "과천시" : "L06",
- "안산시" : "L07",
- "용인시" : "L08",
- "성남시" : "L09",
- "고양시" : "L10",
- "시흥시" : "L11",
- "파주시" : "L12",
- "양주시" : "L13",
- "의정부시" : "L14",
- "김포시" : "L15",
- "의왕시" : "L16",
- "군포시" : "L17",
- "남양주시" : "L18",
- "수원시" : "L19",
- "광주시" : "L20",
- "구리시" : "L21",
- "하남시" : "L22",
- "부산시" : "L23",
- "양산시" : "L24",
- "창원시" : "L25",
- "김해시" : "L26",
- "화성시" : "L27",
- "거제시" : "L28",
- "대구시" : "L29",
- "대전시" : "L30",
- "광주광역시" : "L31",
- "포항시" : "L37"
- }
-
- // 메세지 정의
- let messageIndex = {
- "0" : "노드ID 미입력",
- "1" : "노드ID 중복",
- "2" : "노드ID 10자리수 초과",
- "3" : "교차로명 미입력",
- "4" : "위도 미입력",
- "5" : "형식에 맞지 않는 위도",
- "6" : "경도 미입력",
- "7" : "형식에 맞지 않는 경도",
- "8" : "지역/시(ADDR1) 미입력",
- "9" : "군/구(ADDR2) 미입력",
- "10" : "주소(ADDR3) 미입력",
- "11" : "연등지 항목 미입력",
- "12" : "NODE TYPE 미입력",
- "13" : "형식에 맞지 않는 NODE TYPE",
- "14" : "등록되어 있지 않은 지역"
- }
-
- // 전체 NODE 조회
- function allNodeId() {
- $.ajax({
- url: "/node/getAllNodeId.do",
- async: false,
- cache: false,
- type: "get",
- dataType: "json",
- success: function(result) {
- // var include = result.includes(value.toString());
- // checker.push(include);
- nodeIdData = result;
- }, error: function(error) {
- console.log(error)
- }
- })
- }
-
- // NodeVO 객체
- function NodeVO(nodeid, name, latitude, longitude, addr1, addr2,
- addr3, addnode, ipaddr, useyn, cvimyn, nodeyn, testyn,
- nodetype, regionId){
- this.nodeid = nodeid;
- this.name = name;
- this.latitude = latitude;
- this.longitude = longitude;
- this.addr1 = addr1;
- this.addr2 = addr2;
- this.addr3 = addr3;
- this.addnode = addnode;
- this.ipaddr = ipaddr;
- this.useyn = useyn;
- this.cvimyn = cvimyn;
- this.nodeyn = nodeyn;
- this.testyn = testyn;
- this.nodetype = nodetype;
- this.regionId = regionId;
- }
-
- // NULLCHECKER
- function nullChecker(item) {
- var result = (item == null || item == "" || item == undefined) ? true : false;
- return result;
- }
-
- function regionExcel() {
- $.when(regionArr(region)).done(
- readExcel()
- )
- }
-
- function readExcel() {
- addData = [];
-
- // 검사 여부 초기화
- validateYN = 0;
-
- // CSS 초기화
- $(".batch-popup")[0].style["grid-template-rows"] = "60px 30px 1fr"
- $(".inspection-option")[0].style["display"] = "none"
- $(window)[0].resizeTo(616, 380);
-
- // 엑셀 Parsing
- let input = event.target;
- let reader = new FileReader();
-
- reader.onload = function () {
- let data = reader.result;
- let workBook = XLSX.read(data, { type: 'binary' });
- workBook.SheetNames.forEach(function (sheetName) {
- let rows = XLSX.utils.sheet_to_json(workBook.Sheets[sheetName],
- {header:["NODE ID","교차로","위도","경도","지역(시)","군/구","주소","ADD NODE","IP 주소","사용 여부","CVIM TOPIC","NODE TOPIC","TEST TOPIC","NODE TYPE","권역 ID"]}
- );
- console.log(rows.length);
- rows.forEach((v, i) => {
- let nodeid = String(v['NODE ID'])
- let name = v['교차로']
- let latitude = String(v['위도'])
- let longitude = String(v['경도'])
- let addr1 = v['지역(시)']
- let addr2 = v['군/구']
- let addr3 = v['주소']
- let addnode = v['ADD NODE'] === '연등지' ? 'T' : 'F'
- let ipaddr = v['IP 주소']
- let useyn = v['사용 여부'] === '사용' ? 'Y' : 'N'
- let cvimyn = v['CVIM TOPIC'] === '사용' ? 'Y' : 'N'
- let nodeyn = String(v['NODE TOPIC'] === '사용' ? 'Y' : 'N')
- let testyn = v['TEST TOPIC'] === '사용' ? 'Y' : 'N'
- let nodetype = String(v['NODE TYPE'])
- let test = region[0].filter(value => value.region_name === v['권역 ID'])
- let regionId = test[0] ? test[0].region_id : null
-
- if(i > 1){
- addData.push(
- new NodeVO(
- nodeid,name,latitude,longitude,addr1,
- addr2,addr3,addnode,ipaddr,useyn
- ,cvimyn,nodeyn,testyn,nodetype,regionId
- )
- );
- }
- })
- })
- };
- reader.readAsBinaryString(input.files[0]);
- }
-
- function validateExcel(check){
- obj = null;
- delStr = ""
- result = [];
- resultD = [] // 중복 기반정보
- errList = [];
- message = "";
- $(".inspection-result")[0].innerText = "";
-
- addData.forEach((v, i) => {
- let cnt = 0;
-
- // 노드 조회(중복 검사)
- let checker = [];
- let validate = {
- nodeid : v.nodeid,
- name : v.name,
- err : new Array(15).fill(0)
- };
- checker.push(nodeIdData.includes(v['nodeid']));
- // allNodeId(v['nodeid'], checker)
-
- // NODE ID NULLCHECK
- if(nullChecker(v['nodeid'])){
- validate.err[0] = 1;
- cnt++;
- // alert("엑셀에 NODE ID가 입력되지 않은 항목이 존재합니다.");
- // return
- }
-
- // NODE ID 중복검사
- if(checker[0]){
- validate.err[1] = 1;
- cnt++;
- // alert("엑셀에 NODE ID가 중복된 항목이 존재합니다.")
- // return
- }
- if (check == 'upload2'){
- delStr += v['nodeid'] +','
- }
-
- // NODE ID 10자리 이하 숫자 검사
- if (!nodeIdPattern.test(v['nodeid'])) {
- validate.err[2] = 1;
- cnt++;
- // alert("엑셀에 NODE ID가 10자리 이상 입력된 항목이 존재합니다.");
- // return
- }
-
- // NAME NULLCHECK
- if (nullChecker(v['name'])) {
- validate.err[3] = 1;
- cnt++;
- // alert("엑셀에 교차로가 입력되지 않은 항목이 존재합니다.");
- // return
- }
-
- // 위도 NULLCHECK
- if (nullChecker(v['latitude'])) {
- validate.err[4] = 1;
- cnt++;
- // alert("엑셀에 위도가 입력되지 않은 항목이 존재합니다.");
- // return
- }
-
- // 위도 정규식 검사
- if (!latitudePattern.test(v['latitude'])) {
- validate.err[5] = 1;
- cnt++;
- // alert("엑셀에 위도 입력 시 소수점 포함 앞자리 0~2자리, 뒷자리 0~14자리로 입력해주세요.")
- // return
- }
-
- // 경도 NULLCHECK
- if (nullChecker(v['longitude'])) {
- validate.err[6] = 1;
- cnt++;
- // alert("엑셀에 경도가 입력되지 않은 항목이 존재합니다.");
- // return
- }
-
- // 경도 정규식 검사
- if (!longitudePattern.test(v['longitude'])) {
- validate.err[7] = 1;
- cnt++;
- // alert("엑셀에 경도 입력 시 소수점 포함 앞자리 0~3자리, 뒷자리 0~14자리로 입력해주세요.")
- // return
- }
-
- // 지역 NULLCHECK
- if (nullChecker(v['addr1'])) {
- validate.err[8] = 1;
- cnt++;
- // alert("엑셀에 지역(시)이 입력되지 않은 항목이 존재합니다.");
- // return
- }
-
- // 군/구 NULLCHECK
- if (nullChecker(v['addr2'])) {
- validate.err[9] = 1;
- cnt++;
- // alert("엑셀에 군(구)이 입력되지 않은 항목이 존재합니다.");
- // return
- }
-
- // 주소 NULLCHECK
- if (nullChecker(v['addr3'])) {
- validate.err[10] = 1;
- cnt++;
- // alert("엑셀에 주소가 입력되지 않은 항목이 존재합니다.");
- // return
- }
-
- // ADD NODE NULLCHECK
- if (nullChecker(v['addnode'])) {
- validate.err[11] = 1;
- cnt++;
- // alert("엑셀에 연등지 여부가 입력되지 않은 항목이 존재합니다.");
- // return
- }
-
- // NODE TYPE NULLCHECK
- if (nullChecker(v['nodetype'])) {
- validate.err[12] = 1;
- cnt++;
- // alert("엑셀에 NODE TYPE이 입력되지 않은 항목이 존재합니다.");
- // return
- }
-
- // NODE TYPE 정규식 검사
- if(!ntPattern.test(v['nodetype'])) {
- validate.err[13] = 1;
- cnt++;
- // alert("엑셀에 NODE TYPE 입력 시 형식에 맞게 입력하세요(숫자만 입력 가능)")
- // return
- }
-
- // 지역ID 검사
- if(v['regionId'] == null){
- validate.err[14] = 1;
- v['regionId'] = 'L01';
- // alert("입력하신 권역ID는 등록되지 않은 권역입니다. 기본 설정된 권역ID로 자동 입력됩니다.")
- // return
- }
-
- if(!cnt){
- result.push(v);
- } else {
- resultD.push(v);
- errList.push(validate);
- }
- })
-
- message = "※ 엑셀 데이터 검사 중 예외처리가 발생한 정보는 추가되지 않습니다.\n";
-
- errList.forEach((v1, i1) => {
- message += "\n노드ID : " + v1.nodeid + " / " + "교차로명 : " + v1.name
- + "\n\n<에러항목>\n";
-
- v1.err.forEach((v2, i2) => {
- if(v2){
- message += "○ " + messageIndex[i2] + "\n";
- }
- })
- })
-
- jQuery.ajaxSettings.traditional = true;
-
- $(".inspection-result")[0].innerText = message;
-
- validateYN = 1;
- }
-
- function addNode(arr1){
- let obj1 = JSON.stringify(arr1);
-
- if(arr1.length){
- $.ajax({
- url:"/node/addNode.do",
- async:false,
- type: "get",
- dataType: "json",
- data:{
- jsonData:obj1
- },
- success:function(result){
- if(result==0){
- alert("노드 등록이 정상적으로 처리되지 않았습니다.");
- return
- }
- alert("노드 정보 "+result+"건이 등록 되었습니다.");
- window.close();
- }, error: function(error) {
- console.log(error)
- }
- })
- } else {
- alert("등록할 정보가 존재하지 않습니다.")
- }
- }
-
- function updateNode(arr1){
- let obj1 = JSON.stringify(arr1);
-
- if(arr1.length){
- $.ajax({
- url:"/node/updateMultiNode.do",
- async:false,
- type: "get",
- dataType: "json",
- data:{
- jsonData:obj1
- },
- success:function(result){
- if(result==0){
- alert("노드 수정이 정상적으로 처리되지 않았습니다.");
- return
- }
- alert("노드 정보 "+result+"건이 수정 되었습니다.");
- window.close();
- }, error: function(error) {
- console.log(error)
- }
- })
- } else {
- alert("등록할 정보가 존재하지 않습니다.")
- }
- }
-
- function saveExcel(){
- if(addData.length){
- if(validateYN){
- // 중복 데이터 제외 후 추가
- if($("input[name='option']:checked").val() == 'upload1'){
- if(confirm(result.length + "건의 노드 정보를 추가 하시겠습니까?")){
- // 추가
- addNode(result)
- }
- } else {
- if(confirm(result.length + "건의 노드 정보 추가와 " + resultD.length + "건의 노드 정보 수정을 하시겠습니까?")){
- $.when(addNode(result)).done(
- updateNode(resultD)
- )
- }
- }
- } else {
- alert("엑셀 검사 후 등록이 가능합니다.")
- }
- } else if(!addData.length) {
- alert("엑셀이 등록되지 않았거나, 엑셀 데이터가 존재하지 않습니다.")
- }
- }
- </script>
- </body>
- </html>
|