
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
<template>
<div class="wrap">
<div>
<div class="search-wrap clear-fix">
<div class="float-left">
<h3 class="sub-title">표준노드 목록</h3>
</div>
<div class="float-right">
<select v-model="nodeListSearch.searchType">
<option value="null">검색조건</option>
<option value="node_id">ID</option>
<option value="node_nm">노드명</option>
</select>
<input type="search" placeholder="검색어를 입력 해주세요." v-model="nodeListSearch.searchText" @keyup.enter="nodeSelectList"/>
<button type="button" class="btn-2 green-btn" @click="nodeSelectList()">검색</button>
</div>
</div>
<div>
<table>
<colgroup>
<col style="width: 5%;">
<col style="width: 15%;">
<col style="width: 20%;">
<col style="width: 20%;">
<col style="width: 10%;">
<col style="width: 10%;">
<col style="width: 20%;">
</colgroup>
<thead>
<tr>
<!-- <th rowspan="2">순번</th> -->
<th rowspan="2">ID</th>
<th rowspan="2">읍/면/동</th>
<th rowspan="2">노드명</th>
<!-- <th rowspan="2">노드타입</th> -->
<th colspan="2">좌표</th>
<!-- <th rowspan="2">등록일</th> -->
</tr>
<tr>
<th>위도</th>
<th>경도</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, idx) in nodeList" :key="idx" @click="nodeSelectOne(item)">
<!-- <td data-title="NO">{{ item.id }}</td> -->
<td data-title="ID">{{ item.node_id }}</td>
<td data-title="행정동명">{{ item.dong_nm }}</td>
<td data-title="노드명">{{ item.node_name }}</td>
<!-- <td data-title="노드타입">{{ item.node_type }}</td> -->
<td data-title="위도">{{ item.lat }}</td>
<td data-title="경도">{{ item.lon }}</td>
<!-- <td data-title="등록날짜">{{ dateHyphen(item.updatedate) }}</td> -->
<td></td>
</tr>
</tbody>
</table>
</div>
<div class="bottom-wrap">
<PaginationButton
v-model:currentPage="nodeListSearch.currentPage"
:per-page="nodeListSearch.perPage" :total-count="nodeListCount" :max-range="5"
:click="nodeSelectList" />
</div>
</div>
<div>
<div class="sub-title-wrap">
<h3 class="sub-title">표준노드 정보관리</h3>
<span class="btn-2 green-btn" @click="nodeInsertPage">신규등록</span>
</div>
<div>
<table>
<colgroup>
<col style="width: 10%;">
<col style="width: 10%;">
<col style="width: 30%;">
<col style="width: 20%;">
<col style="width: 30%;">
</colgroup>
<tbody>
<tr>
<th colspan="2">ID</th>
<td>{{ node.node_id }}</td>
<th>등록일</th>
<td>{{ node.updatedate }}</td>
</tr>
<tr>
<th colspan="2">노드명</th>
<td><input type="text" v-model="node.node_name"></td>
<th>수정일</th>
<td></td>
</tr>
<tr>
<th colspan="2">읍/면/동</th>
<!-- <td><input type="text" v-model="node.node_type"></td> -->
<td><input type="text" v-model="node.dong_nm"></td>
<th>등록자</th>
<td></td>
</tr>
<tr>
<th rowspan="2">좌표 <button type="button" class="btn-2 gray-btn" @click="[map_open = true, openMap()]">좌표수정</button></th>
<th class="second">위도</th>
<td>{{ node.lat }}</td>
<th>수정자</th>
<td></td>
</tr>
<tr>
<th class="second">경도</th>
<td>{{ node.lon }}</td>
</tr>
</tbody>
</table>
</div>
<div class="btn-wrap">
<button type="button" class="btn-2 green-btn" @click="modal_update = true">수정</button>
<button type="button" class="btn-2 gray-btn" @click="modal_delete = true">삭제</button>
</div>
</div>
<div>
<div class="sub-title-wrap">
<h3 class="sub-title">파일 업로드</h3>
</div>
<div>
<table>
<colgroup>
<col style="width: 30%;">
<col style="width: 70%;">
</colgroup>
<tbody>
<tr>
<th>ID</th>
<td class="txt-left">
<input type="file" name="" id="fileBtn">
<label for="fileBtn" class="btn-2 green-btn">
파일선택
</label>
<button type="button" class="gray-btn" @click="nodeExcelInsert">등록</button>
</td>
</tr>
<tr>
<th>양식다운로드</th>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="modal-wrap" v-if="modal_insert == true">
<div class="modal-bg">
</div>
<div class="modal">
<p>노드를 <span class="txt-point">등록</span>하시겠습니까?</p>
<div class="btn-wrap">
<button type="button" class="green-btn" @click="nodeInsert">확인</button>
<button type="button" class="gray-btn" @click="modal_insert = false">취소</button>
</div>
</div>
</div>
<div class="modal-wrap" v-if="modal_update == true">
<div class="modal-bg">
</div>
<div class="modal">
<p>수정하신 정보를 <span class="txt-point">저장</span>하시겠습니까?</p>
<div class="btn-wrap">
<button type="button" class="green-btn" @click="nodeUpdate">확인</button>
<button type="button" class="gray-btn" @click="modal_update = false">취소</button>
</div>
</div>
</div>
<div class="modal-wrap" v-if="modal_delete == true">
<div class="modal-bg">
</div>
<div class="modal">
<p>
해당 기능은 데이터 삭제 기능입니다.<br>
데이터 삭제 후, 조회에서 해당 데이터를 확인할 수 없습니다.<br>
삭제를 원하시면 아래 삭제 버튼을 눌러주세요.
</p>
<div class="btn-wrap">
<button type="button" class="green-btn" @click="nodeDelete">삭제</button>
<button type="button" class="gray-btn" @click="modal_delete = false">취소</button>
</div>
</div>
</div>
<div class="modal-wrap" v-if="map_open">
<div class="modal-bg">
</div>
<div class="modalMap">
<div class="search">
<h2>교차로 검색</h2>
<dongSelectList @setDongCd="setDongCd"></dongSelectList>
</div>
<button type="button" class="green-btn" @click="searchNode">검색</button>
<OpenLayers ref="open_layers"/>
<label>위도 : </label>
<input style="width: 20rem" type="text" v-model="map_lat" disabled/>
<label>경도 : </label>
<input style="width: 20rem" type="text" v-model="map_lon" disabled/>
<label>교차로명 : </label>
<input style="width: 20rem" type="text" v-model="node.node_name" disabled/>
<div class="btn-wrap">
<button type="button" class="green-btn" @click="selectCoordinate">선택</button>
<button type="button" class="gray-btn" @click="closeMap">취소</button>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
import PaginationButton from '../../component/pagination/PaginationButton.vue';
import COMMON_UTIL from '../../../resources/js/commonUtil.ts';
import OpenLayers from "../../component/OpenLayers.vue";
import {
vworldBaseLayer,
vworldGrayLayer,
vworldMidnightLayer,
vworldHybridLayer,
vworldSatelliteLayer,
} from "../../component/OpenLayersMap.vue";
import {baseStyles} from '../../component/OpenLayersStyle.vue';
import dongSelectList from '../../component/dongSelectList.vue';
import { transform } from 'ol/proj';
export default {
data:() => {
return {
nodeListSearch: {
currentPage: 1,
perPage: 10,
searchType: null,
searchText: null
},
node: {
node_id: null,
node_name: null,
node_type: null,
lat: null,
lon: null,
// updatedate: null,
dong_cd: '22030',
dong_nm: null
},
address: {},
nodeListCount: 0,
nodeList: [],
//modal
modal_insert: false,
modal_update: false,
modal_delete: false,
id_disabled: false,
//좌표 modal
map_open: false,
map_lat: null,
map_lon: null,
};
},
methods: {
//좌표수정 지도 열기
async openMap() {
const vm = this;
//OpenLayers 랜더링 후 접근
await vm.$nextTick();
//수정 전 좌표 modal에서 보여주기
vm.map_lat = vm.node.lat;
vm.map_lon = vm.node.lon;
//기본맵 세팅
vm.$refs.open_layers.setBaseMap(vworldBaseLayer);
//행정동 레이어
//this.$refs.open_layers.addVectorLayerByUrl('/testDongGeoJson.json','testMap','EPSG:4326', baseStyles['labelStyle'],'label');
vm.$refs.open_layers.addVectorLayerByUrl('/common/getDongGeoJson.json','testMap','EPSG:5181', baseStyles['MultiPolygon'],'MultiPolygon',vm.node.dong_cd);
if(vm.map_lat != null) {
//노드위치로 이동
vm.$refs.open_layers.removeLayer('point1');
vm.$refs.open_layers.setCenterPosition(vm.node.lat,vm.node.lon,'EPSG:4326');
vm.$refs.open_layers.createIcon(vm.node.lat,vm.node.lon,'/client/resources/images/icon/fin.png',0.3, 'point1','EPSG:4326');
} else {
vm.$refs.open_layers.setCenterPosition(265352.91811139905,340098.7926937433,'EPSG:5181');
vm.$refs.open_layers.zoomChange(14.5);
};
},
closeMap() {
const vm = this;
vm.$refs.open_layers.removeLayerAll();
vm.map_open = false;
},
//지도 클릭 이벤트
childClick(prop,coordinate){
const vm = this;
console.log(prop);
console.log("coordinate",coordinate);
// 레이어 삭제
vm.$refs.open_layers.removeLayer('point1');
// Icon 그리기
vm.$refs.open_layers.createIcon(coordinate[1],coordinate[0],'/client/resources/images/icon/fin.png',0.3, 'point1','EPSG:5181');
//클릭위치로 이동
// this.$refs.open_layers.setCenterPosition(coordinate[0],coordinate[1],'EPSG:5181');
//좌표계 변환
var changeCoordinate = transform([coordinate[0],coordinate[1]],'EPSG:5181','EPSG:4326');
console.log("lat 바꿈",changeCoordinate[1]);
console.log("lon 바꿈",changeCoordinate[0]);
vm.map_lat = changeCoordinate[1];
vm.map_lon = changeCoordinate[0];
},
//좌표 선택 완료
selectCoordinate() {
const vm = this;
vm.node.lat = vm.map_lat;
vm.node.lon = vm.map_lon;
vm.map_open = false;
},
// 좌표수정에서 교차로 검색시 동레이어, 노드좌표 찍어주기
searchNode() {
const vm = this;
//기존 레이어 삭제
vm.$refs.open_layers.removeLayer('testMap');
vm.$refs.open_layers.removeLayer('point1');
//동 레이어 그리기
vm.$refs.open_layers.addVectorLayerByUrl('/common/getDongGeoJson.json','testMap','EPSG:5181', baseStyles['MultiPolygon'],'MultiPolygon',vm.address.dong_dong_cd);
axios({
url: '/node/nodeSelectOne.json',
method: 'post',
headers: {
'Content-Type': "application/json; charset=UTF-8"
},
data: {'node_id' : vm.address.node_id}
}).then(function (response) {
console.log("searchNode response : ",response.data);
vm.$refs.open_layers.createIcon(response.data.lat,response.data.lon,'/client/resources/images/icon/fin.png',0.3, 'point1','EPSG:4326');
vm.$refs.open_layers.setCenterPosition(response.data.lat,response.data.lon,'EPSG:4326');
vm.$refs.open_layers.zoomChange(19);
}).catch(function (error) {
console.log("serchNode error : ", error);
alert("검색에 실패 하였습니다. 관리자에게 문의하세요.");
})
},
//노드 엑셀 업로드
nodeExcelInsert() {
const vm = this;
var form = new FormData();
var file = document.getElementById("fileBtn");;
console.log(file.files[0]);
form.append("file", file.files[0]);
axios({
url: '/node/nodeExcelRead.json',
method: 'post',
hearders: {
'Content-Type': "multipart/form-data",
},
data: form
}).then(function (response) {
console.log("nodeExcelInsert - response : ", response.data);
let insert = response.data.insert;
let error = response.data.error;
if (insert > 0 && error > 0) {
alert(insert + "건의 노드 등록완료, " + error + "건은 이미 ID가 존재하는 데이터 입니다.")
vm.nodeSelectList();
} else if(insert === 0) {
alert("업로드 파일의 모든 데이터(" + error + "건)는 이미 ID가 존재하는 데이터 입니다.")
vm.nodeSelectList();
} else if(insert > 0 && error === 0) {
alert(insert + "건의 노드 등록완료.")
vm.nodeSelectList();
}
}).catch(function (error) {
console.log("nodeExcelInsert - error", error);
alert("파일 등록 오류, 관리자에게 문의해주세요.")
})
},
//노드목록 조회
nodeSelectList() {
const vm = this;
axios({
url: '/node/nodeSelectList.json',
method: 'post',
headers: {
'Content-Type': "application/json; charset=UTF-8",
},
data: vm.nodeListSearch
}).then(function (response) {
console.log("nodeSelectList - response : ", response.data);
vm.nodeListCount = response.data.nodeListCount;
vm.nodeList = response.data.nodeList;
}).catch(function (error) {
console.log("nodeSelectList - error : ", error);
alert("노드 목록 조회 오류, 관리자에게 문의해주세요.");
});
},
//노드 수정
nodeUpdate() {
const vm = this;
axios({
url: '/node/nodeUpdate.json',
method: 'post',
headers: {
'Content-Type': "application/json; charset=UTF-8"
},
data: vm.node
}).then(function (response) {
console.log("nodeUpdate - response : ", response.data);
let result = response.data;
if( result > 0) {
alert("노드 수정을 완료 하였습니다.");
vm.modal_update = false;
vm.nodeSelectList();
vm.node = {
node_id: null,
node_name: null,
node_type: null,
lat: null,
lon: null,
updatedate: null
};
vm.id_disabled = false;
} else {
alert("수정 실패, 관리자에게 문의해주세요.");
vm.modal_update = false;
}
}).catch( function (error) {
console.log("nodeUpdate - error : ", error);
alert("노드수정 오류, 관리자에게 문의해주세요.");
vm.modal_update = false;
})
},
//노드 삭제
nodeDelete() {
const vm = this;
axios({
url: '/node/nodeDelete.json',
method: 'post',
headers: {
'Content-Type': "application/json; charset=UTF-8"
},
data: vm.node
}).then( function (response) {
console.log("nodeDelete - response : ", response.data);
let result = response.data;
if( result > 0) {
alert("노드 삭제를 완료 하였습니다.");
vm.modal_delete = false;
vm.nodeSelectList();
vm.node = {
node_id: null,
node_name: null,
node_type: null,
lat: null,
lon: null,
updatedate: null
};
vm.id_disabled = false;
} else {
alert("삭제 실패, 관리자에게 문의해주세요.");
vm.modal_delete = false;
}
}).catch( function (error) {
console.log("nodeDelete - error : ", error);
alert("노드삭제 오류, 관리자에게 문의해주세요.");
vm.modal_delete = false;
})
},
//노드 상세 조회
nodeSelectOne(nodeOne) {
const vm = this;
axios({
url: '/node/nodeSelectOne.json',
method: 'post',
headers: {
'Content-Type': "application/json; charset=UTF-8"
},
data: nodeOne
}).then(function(response) {
console.log("nodeSelectOne - response : ", response.data);
vm.node = response.data;
this.id_disabled = true;
}).catch(function(error) {
console.log("nodeSelectOne - error : ", error);
});
},
//dongSelectList 컴포넌트에서 선택된 dong_cd 셋팅
setDongCd(value) {
console.log("value : ", value);
this.address = value;
},
//날짜에 '-' 넣기
dateHyphen(date) {
return COMMON_UTIL.dateHyphen(date);
},
nodeInsertPage() {
this.$router.push({ path: '/NodeAddForm.page'})
}
},
watch: {},
computed: {},
components: {
PaginationButton:PaginationButton,
OpenLayers: OpenLayers,
dongSelectList: dongSelectList
},
mounted() {
console.log("Main4 mounted");
this.nodeSelectList();
},
};
</script>
<style scoped>
.wrap {
width: 155rem;
margin: 100px auto;
}
.search-wrap {
margin-bottom: 30px;
}
.search-wrap input,
.search-wrap select {
height: 22.5px;
border-radius: 3px;
border: 1px solid #949292;
}
.float-left {
float: left;
}
.float-left .sub-title,
.sub-title-wrap .sub-title {
font-size: 20px;
}
.float-right {
float: right;
}
.sub-title-wrap>* {
display: inline-block;
vertical-align: middle;
}
.sub-title-wrap>*:not(:last-child) {
margin-right: 2rem;
}
.full {
width: 100%;
}
.txt-left {
text-align: left;
}
.txt-left .green-btn {
margin-right: 2rem;
}
.btn-2 {
display: inline-block;
padding: 0.3rem 2rem;
font-size: 13.333px;
}
label.btn-2 {
cursor: pointer;
}
.clear-fix::after {
content: "";
display: block;
clear: both;
}
.search-wrap .float-right form>*:not(:last-child) {
margin-right: 1rem;
}
table {
width: 100%;
text-align: center;
border-collapse: collapse;
}
th,
td {
border-left: none;
border-right: none;
}
td input{width: -webkit-fill-available;}
table th {
padding: 15px;
color: #fff;
background-color: #13833b;
border-bottom: 1px solid #e5e5dd;
}
table td {
padding: 10px;
border-bottom: 1px solid #e5e5dd;
}
table tbody th.second {
background-color: #31a257;
}
table tr:nth-child(odd) {
background-color: #f7f6f6;
}
table tr:nth-child(even) {
background-color: #fdfdf2;
}
.bottom-wrap {
position: relative;
padding: 1rem 0;
}
.pg-wrap {
text-align: center;
}
.pg-item {
display: inline-block;
padding: 10px;
color: #949292;
}
.pg-item.prev,
.pg-item.next,
.pg-item.active {
color: #13833b;
}
#fileBtn::file-selector-button {
display: none;
}
.btn-wrap {
text-align: right;
margin-top: 15px;
}
.btn-wrap>*:not(:last-child) {
margin-right: 15px;
}
.modal-bg {
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .6);
}
.modal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
max-width: 350px;
padding: 5rem;
z-index: 2;
background-color: #fff;
border-radius: 1rem;
text-align: center;
}
.modalMap {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90%;
padding: 5rem;
z-index: 2;
background-color: #fff;
border-radius: 1rem;
}
.modal .btn-wrap {
text-align: center;
}
.txt-point {
color: #13833b;
}
</style>