<template> <div class="container"> <div class="page-titleZone flex justify-between"> <p class="main-title">진단대상관리 > 진단대상DB관리</p> <PageNavigation /> </div> <div class="content"> <div class="row"> <div class="content-titleZone"> <p class="box-title">>검색조건</p> </div> <div class="searchbar-zone"> <div class="flex justify-start align-center"> <span class="option-title">DBMS유형</span> <select v-model="dbListSearch.dbmsType" class="square-select"> <option value="all">전체</option> <option value="PostgreSQL">PostgreSQL</option> </select> <span class="option-title">DBMS명</span> <div class="search-square"> <input v-model="dbListSearch.searchText" type="text" class="square-input" placeholder="DBMS명" /> <button @click="selectDbList" class="square-button"> <svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon> </button> </div> </div> </div> <div class="table-zone"> <div class="flex justify-start"> <button class="blue-btn small-btn" @click="deleteDbData()">선택항목 삭제</button> <button class="blue-btn small-btn" @click="updateDbData()">선택항목 수정</button> <button class="blue-btn small-btn" @click="connectDb()">접속테스트</button> <button class="blue-btn small-btn" @click="collectSchema()">스키마수집</button> </div> <table class="list-table"> <colgroup> <col style="width: 5%" /> <col style="width: 5%" /> <col style="width: 5%" /> <col style="width: 8%" /> <col style="width: 8%" /> <col style="width: 5%" /> <col style="width: 12%" /> <col style="width: 12%" /> <col style="width: 5%" /> <col style="width: 5%" /> <col style="width: 5%" /> <col style="width: 5%" /> <col style="width: 20%" /> </colgroup> <thead> <tr> <th>No</th> <th>선택</th> <th>연결상태</th> <th>*DBMS명</th> <th>*DBMS유형</th> <th>DBMS버전</th> <th>*연결 URL</th> <th>*드라이버명</th> <th>*DB접속계정ID</th> <th>*DB접속계정암호</th> <th>*기관명</th> <th>*정보시스템명</th> <th>설명</th> </tr> </thead> <tbody class="dbData" > <tr v-for="(db, index) in dbList" :key="index" @mouseover="() => handleSchemaClick(index)" @click="selectSchemaList" > <td>{{ index + 1 }}</td> <td> <input type="checkbox" :checked="isSelected(index)" @click="handleClick(index)" /> </td> <td>{{ getConnectStatus(db.dbms_connect) }}</td> <td><input type="text" v-model="db.dbms_name" /></td> <td> <select v-model="db.dbms_type" @change="updateDriveNm(index)"> <option value="PostgreSQL">PostgreSQL</option> <option value="MariaDB">MariaDB</option> </select> </td> <td>{{ db.dbms_version }}</td> <td><input type="text" v-model="db.dbms_url_port" style="width: 300px;"/></td> <td><input type="text" v-model="db.dbms_drive_nm" /></td> <td><input type="text" v-model="db.dbms_connect_id" /></td> <td><input type="password" v-model="db.dbms_connect_pw" /></td> <td><input type="text" v-model="db.dbms_ag_nm" /></td> <td><input type="text" v-model="db.dbms_system_nm" /></td> <td><input type="text" v-model="db.dbms_explain" style="width: 300px;"/></td> </tr> <tr> <td colspan="3" style="text-align: left"> <button class="blue-btn small-btn" @click="insertDbData()">신규 DB 추가</button> </td> <td><input type="text" v-model="dbInput.dbms_name" /></td> <td> <select v-model="dbInput.dbms_type" @change="updateDriveNm_input"> <option value="" disabled selected>선택</option> <option value="PostgreSQL">PostgreSQL</option> </select> </td> <td></td> <td><input type="text" v-model="dbInput.dbms_url_port" style="width: 300px;"/></td> <td><input type="text" v-model="dbInput.dbms_drive_nm" /></td> <td><input type="text" v-model="dbInput.dbms_connect_id" /></td> <td><input type="password" v-model="dbInput.dbms_connect_pw" /></td> <td><input type="text" v-model="dbInput.dbms_ag_nm" /></td> <td><input type="text" v-model="dbInput.dbms_system_nm" /></td> <td><input type="text" v-model="dbInput.dbms_explain" style="width: 300px;"/></td> </tr> </tbody> </table> </div> <PaginationButton v-model:currentPage="dbListSearch.currentPage" :perPage="dbListSearch.perPage" :totalCount="dbListCount" :maxRange="5" /> </div> <div class="content-titleZone"> <p class="box-title">DBMS 스키마 정보</p> </div> <div class="table-zone"> <table class="list-table" style="text-align: center"> <colgroup> <col width="5%" /> <col width="10%" /> <col width="20%" /> <col width="20%" /> <col width="40%" /> </colgroup> <thead> <tr> <th>No.</th> <th>수집 제외</th> <th>DB 접속 대상</th> <th>스키마명</th> <th>설명</th> </tr> </thead> <tbody> <tr v-for="(item, index) in schemaList" :key="item.schema_id"> <td>{{ index + 1 }}</td> <td> <input type="checkbox" v-model="selectedSchemaIds" :value="item.schema_id" /> </td> <td>{{ item.dbms_name }}</td> <td>{{ item.schema_name }}</td> <td> <input type="text" :placeholder="item.schema_explain" :disabled="!selectedSchemaIds.includes(item.schema_id)" v-model="item.updatedSchemaExplain" style="width: 600px;" /> </td> </tr> </tbody> </table> <div class="flex justify-end"> <button class="red-btn small-btn" @click="setSchema()">수집제외 여부, 설명 저장</button> </div> </div> <PaginationButton v-model:currentPage="schemaCurrentPage" :perPage="schemaPerPage" :totalCount="schemaTotalCount" :maxRange="5" :click="handlePageChange" /> </div> </div> </template> <script> import PageNavigation from '../../component/PageNavigation.vue'; import PaginationButton from '../../component/paginationbutton.vue'; import SvgIcon from '@jamescoyle/vue-icon'; import { mdiMagnify } from '@mdi/js'; import axios from 'axios'; export default { data() { return { searchPath: mdiMagnify, inputValue: null, dbList: [], dbInput: { dbms_name: '', dbms_type: '', dbms_version: '', dbms_url_port: '', dbms_drive_nm: '', dbms_connect: '', dbms_connect_id: '', dbms_connect_pw: '', dbms_ag_nm: '', dbms_system_nm: '', dbms_explain: '', user_id: $cookies.get('USER_ID'), }, selectedDb: null, // 선택된 DB의 인덱스를 저장하는 변수 selectedSchema: null, // 선택된 스키마 행의 인덱스를 저장하는 변수 userName: $cookies.get('USER'), selectedDbIndex: null, schemaList: [], dbListSearch: { currentPage: 1, perPage: 10, user_id: $cookies.get('USER_ID'), dbmsType: 'all', searchText: null, }, dbListCount: 0, dbIdx: 0, /* ---------- 스키마 목록 --------- */ schemaCurrentPage: 1, schemaPerPage: 10, schemaTotalCount: 0, schemaIndex: 0, selectedSchemaIds: [], //선택한 스키마 id 배열 update_schemaList: [], // 업데이트할 스키마 목록 update_schemaExplain: '', }; }, methods: { // db유형마다 다른 driver명이 되도록 updateDriveNm_input() { if (this.dbInput.dbms_type === 'PostgreSQL') { this.dbInput.dbms_url_port = 'jdbc:postgresql://{ip}:{port}/{db명}'; this.dbInput.dbms_drive_nm = 'org.postgresql.Driver'; } }, updateDriveNm(index) { if (this.dbList[index].dbms_type === 'PostgreSQL') { this.dbList[index].dbms_url_port = 'jdbc:postgresql://{ip}:{port}/{db명}'; this.dbList[index].dbms_drive_nm = 'org.postgresql.Driver'; } }, // 연결 상태 확인 getConnectStatus(connect) { switch (connect) { case '0': return '연결 필요'; case '1': return '연결 성공'; } }, isSelected(index) { // 현재 인덱스가 선택된 인덱스인지 확인 return this.selectedDb === index; }, handleClick(index) { // 체크박스 클릭 시 실행되는 메서드 if (this.selectedDb === index) { this.selectedDb = null; } else { this.selectedDb = index; } }, handleSchemaClick(index) { this.selectedSchema = index; }, insertDbData: function () { const vm = this; const inputData = vm.dbInput; // 유효성 검사 if ( !vm.dbInput.dbms_name || !vm.dbInput.dbms_type || !vm.dbInput.dbms_url_port || !vm.dbInput.dbms_drive_nm || !vm.dbInput.dbms_connect_id || !vm.dbInput.dbms_connect_pw || !vm.dbInput.dbms_ag_nm || !vm.dbInput.dbms_system_nm ) { if (!vm.dbInput.dbms_name) { vm.$showAlert('error', 'DBMS명은 반드시 입력해야 합니다.'); vm.$refs.dbms_name.focus(); } else if (!vm.dbInput.dbms_type) { vm.$showAlert('error', 'DBMS유형은 반드시 선택해야 합니다.'); vm.$refs.dbms_type.focus(); } else if (!vm.dbInput.dbms_url_port) { vm.$showAlert('error', '연결 URL은 반드시 입력해야 합니다.'); vm.$refs.dbms_url_port.focus(); } else if (!vm.dbInput.dbms_drive_nm) { vm.$showAlert('error', '드라이버명은 반드시 입력해야 합니다.'); vm.$refs.dbms_drive_nm.focus(); } else if (!this.dbInput.dbms_connect_id) { vm.$showAlert('error', 'DB접속계정ID는 반드시 입력해야 합니다.'); vm.$refs.dbms_connect_id.focus(); } else if (!vm.dbInput.dbms_connect_pw) { vm.$showAlert('error', 'DB접속계정암호는 반드시 입력해야 합니다.'); vm.$refs.dbms_connect_pw.focus(); } else if (!vm.dbInput.dbms_ag_nm) { vm.$showAlert('error', '기관명은 반드시 입력해야 합니다.'); vm.$refs.dbms_ag_nm.focus(); } else if (!vm.dbInput.dbms_system_nm) { vm.$showAlert('error', '정보시스템명은 반드시 입력해야 합니다.'); vm.$refs.dbms_system_nm.focus(); } return; } axios({ url: 'insertDbData.json', method: 'post', headers: { 'Content-Type': 'application/json; charset=UTF-8', }, data: inputData, }) .then(function (response) { vm.selectDbList(); }) .catch(function (error) { console.log('insertDbData - error : ', error); vm.$showAlert('error', 'insertDbData 오류'); }); }, selectDbList: function () { const vm = this; axios({ url: 'selectDbList.json', method: 'post', headers: { 'Content-Type': 'application/json; charset=UTF-8', }, data: vm.dbListSearch, }) .then(function (response) { vm.selectedDb = null; vm.dbList = response.data.dbList; vm.dbListCount = response.data.dbListCount; vm.dbIdx = vm.dbListCount - (vm.dbListSearch.currentPage - 1) * vm.dbListSearch.perPage; }) .catch(function (error) { console.log('error', 'selectDbList - error'); vm.$showAlert('error', 'selectDbList 오류'); }); }, connectDb: function () { const vm = this; if (vm.selectedDb == null) { vm.$showAlert('error', '접속 테스트할 DB를 선택해주세요!'); return; } axios({ url: 'connectDb.json', method: 'post', headers: { 'Content-Type': 'application/json; charset=UTF-8', }, data: vm.dbList[vm.selectedDb], }) .then(function (response) { console.log(response.data); if (response.data == 1) { vm.$showAlert('response', 'DB 접속이 성공되었습니다!'); vm.selectDbList(); } else { vm.$showAlert('error', '접속이 실패했습니다! DB 정보를 다시 확인해주세요!'); } }) .catch(function (error) { console.log('selectDbList - error : ', error); vm.$showAlert('error', '접속이 실패했습니다! DB 정보를 다시 확인해주세요'); vm.selectDbList(); }); }, collectSchema: function () { const vm = this; if (vm.selectedDb == null) { vm.$showAlert('error', '스키마를 수집할 DB를 선택해주세요!'); return; } if (vm.dbList[vm.selectedDb].dbms_connect != 1) { vm.$showAlert('error', '접속 테스트가 완료된 DB를 선택해주세요!'); return; } axios({ url: 'collectSchema.json', method: 'post', headers: { 'Content-Type': 'application/json; charset=UTF-8', }, data: vm.dbList[vm.selectedDb], }) .then(function (response) { console.log(response.data); if (response.data == 1) { vm.$showAlert('response', '스키마 수집이 성공되었습니다!'); vm.selectDbList(); } }) .catch(function (error) { console.log('selectDbList - error : ', error); vm.$showAlert('error', '스키마 수집이 실패했습니다! DB 정보를 다시 확인해주세요'); }); }, deleteDbData: function () { const vm = this; if (vm.selectedDb == null) { vm.$showAlert('error', '삭제할 DB를 선택해주세요!'); return; } axios({ url: 'deleteDbData.json', method: 'post', headers: { 'Content-Type': 'application/json; charset=UTF-8', }, data: vm.dbList[vm.selectedDb], }) .then(function (response) { vm.$showAlert('response', 'DB가 삭제되었습니다!'); vm.selectDbList(); }) .catch(function (error) { console.log('deleteDbData - error : ', error); vm.selectDbList(); }); }, // DB 데이터 수정 updateDbData: function () { const vm = this; if (vm.selectedDb == null) { vm.$showAlert('error', '수정할 DB를 선택해주세요!'); return; } axios({ url: 'updateDbData.json', method: 'post', headers: { 'Content-Type': 'application/json; charset=UTF-8', }, data: vm.dbList[vm.selectedDb], }) .then(function (response) { vm.$showAlert('response', 'DB가 수정되었습니다!'); vm.selectDbList(); }) .catch(function (error) { console.log('updateDbData - error : ', error); vm.selectDbList(); }); }, //스키마 정보 수집 selectSchemaList() { const vm = this; if (vm.dbList && vm.dbList.length > vm.selectedSchema) { vm.selectedDbIndex = vm.dbList[vm.selectedSchema].dbms_id; } axios({ url: '/selectSchemaList.json', method: 'post', headers: { 'Content-Type': 'application/json; charset=UTF-8', }, data: { currentPage: vm.schemaCurrentPage, perPage: vm.schemaPerPage, dbms_id: vm.selectedDbIndex, }, }) .then((res) => { console.log('스키마 정보 수집 응답 : ', res.data); // 수집 제외할 스키마 id const checkedSchemaIds = res.data.schemaList .filter((item) => item.schema_yn === 'n') .map((item) => item.schema_id); vm.selectedSchemaIds = checkedSchemaIds; vm.schemaList = res.data.schemaList.map((item) => { // explain을 수정하지 않는 경우 if (item.schema_yn === 'n' && !item.updatedSchemaExplain) { item.updatedSchemaExplain = item.schema_explain; } return item; }); vm.schemaTotalCount = res.data.schemaListCount; console.log('카운트 : ', vm.schemaTotalCount); vm.schemaIndex = vm.schemaTotalCount - (vm.schemaCurrentPage - 1) * vm.schemaPerPage; }) .catch((err) => { console.log('스키마 정보 수집 에러 : ', err); vm.$showAlert('error', '스키마 수집 에러'); }); }, /* 수정 정보 저장 하기 */ setSchema() { console.log('선택된 스키마 ID : ', this.selectedSchemaIds); const vm = this; // 수집 제외 선택 후 설명 입력 안하면 경고창 const hasUndefinedExplain = vm.schemaList.some( (item) => vm.selectedSchemaIds.includes(item.schema_id) && item.updatedSchemaExplain === undefined ); if (hasUndefinedExplain) { vm.$showAlert('error', '설명을 입력해주세요.'); return; } vm.update_schemaList = vm.schemaList.map((item) => { //제외하지 않는 스키마의 설명 null로 설정 if (!vm.selectedSchemaIds.includes(item.schema_id)) { item.updatedSchemaExplain = null; } return { schema_id: item.schema_id, schema_yn: vm.selectedSchemaIds.includes(item.schema_id) ? 'n' : 'y', schema_explain: item.updatedSchemaExplain, }; }); console.log('update_schemaList:', vm.update_schemaList); axios({ url: '/updateSchema.json', method: 'post', headers: { 'Content-Type': 'application/json; charset=UTF-8', }, data: vm.update_schemaList, }) .then((res) => { console.log('스키마 정보 수정 응답 : ', res.data); if (res.data > 0) { vm.$showAlert('response', '변경 내용 저장 완료'); // 2초 뒤 재렌더링 setTimeout(function () { location.reload(); }, 1000); } }) .catch((err) => { console.log('스키마 정보 수정 에러 : ', err); vm.$showAlert('error', '스키마 수정 에러'); }); }, // 페이지네이션 클릭 이벤트 handlePageChange(pageNumber) { this.schemaCurrentPage = pageNumber; }, }, watch: { 'dbListSearch.currentPage': function () { this.selectDbList(); }, schemaCurrentPage(newPage, oldPage) { if (newPage !== oldPage) { this.selectSchemaList(); } }, }, computed: { PaginationButton: PaginationButton, }, components: { PageNavigation: PageNavigation, PaginationButton: PaginationButton, SvgIcon: SvgIcon, }, mounted() { console.log('main mounted'); this.selectDbList(); }, }; </script>