
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
File name
Commit message
Commit date
<template>
<div v-show="isModalOpen" class="modal-wrapper">
<div class="modal-container large-modal">
<div class="modal-title">
<div class="flex justify-between align-center">
<h2>데이터베이스 연결</h2>
<button class="close-btn" @click="$emit('closePopup')">
<svg-icon type="mdi" :width="20" :height="20" :path="closePath"></svg-icon>
</button>
</div>
</div>
<div class="modal-content-monthly" v-show="currentPage == 1">
<div class="table-zone">
<table class="form-table">
<colgroup>
<col style="width: 25%" />
<col style="width: 75%" />
</colgroup>
<tbody v-if="jobItm.itm != null">
<tr>
<th>연계정보 타입</th>
<td>
<div class="input-container flex">
<label class="radio-label">
<input type="radio" name="radio" :value="false" class="custom-radiobox" @change="successAt = false" v-model="jobItm.itm_option_bool" />
<span>직접입력</span>
</label>
<label class="radio-label">
<input type="radio" name="radio" :value="true" class="custom-radiobox" @change="successAt = false" v-model="jobItm.itm_option_bool" />
<span>불러오기</span>
</label>
</div>
</td>
</tr>
<tr v-show="jobItm.itm_option_bool">
<th>연계정보</th>
<td>
<input type="text" class="half-input" disabled :value="linkConnectionDB.conectNm +
'(' +
linkConnectionDB.conectIp +
')'
" v-if="linkConnectionDB.conectNm != null" />
<input type="text" class="half-input" disabled v-else />
<button class="blue-border-btn small-btn" @click="dbConSearchOpen(true)"> 검색 </button>
</td>
</tr>
<tr>
<th>DMBS</th>
<td>
<select id="databaseType" @change="successAt = false" class="square-select half-input" v-model="inputConnectionDB.databaseType" :disabled="jobItm.itm_option_bool">
<option v-for="(itm, index) in databaseTypeList" :key="index" :value="itm.key"> {{ itm.value }} </option>
</select>
</td>
</tr>
<tr>
<th>IP</th>
<td>
<input id="conectIp" type="text" @input="successAt = false" class="half-input" v-model="inputConnectionDB.conectIp" placeholder="127.0.0.1" :disabled="jobItm.itm_option_bool" />
</td>
</tr>
<tr>
<th>PORT</th>
<td>
<input id="conectPort" type="text" @input="successAt = false" class="half-input" v-model="inputConnectionDB.conectPort" :disabled="jobItm.itm_option_bool" />
</td>
</tr>
<tr>
<th>DB 명</th>
<td>
<input id="databaseNm" type="text" @input="successAt = false" class="half-input" v-model="inputConnectionDB.databaseNm" placeholder="데이터베이스명 OR 스키마명" :disabled="jobItm.itm_option_bool" />
</td>
</tr>
<tr>
<th>접속ID</th>
<td>
<input type="text" class="half-input" @input="successAt = false" v-model="inputConnectionDB.userId" placeholder="접속 ID" :disabled="jobItm.itm_option_bool" />
</td>
</tr>
<tr>
<th>접속PW</th>
<td>
<input type="password" class="half-input" @input="successAt = false" v-model="inputConnectionDB.userPassword" placeholder="접속 PW" autocomplete="new-password" :disabled="jobItm.itm_option_bool" />
</td>
</tr>
</tbody>
</table>
<div class="content-titleZone flex justy justify-between align-center mt20">
<p class="box-title">데이터베이스 연결 결과</p>
<button class="blue-border-btn small-btn" @click="dataBaseConnectionCheck()"> 접속확인 </button>
</div>
<div class="table-zone">
<table class="list-table">
<colgroup>
<col width="10%" />
<col width="10%" />
<col width="80%" />
</colgroup>
<thead>
<tr>
<th>No</th>
<th>접속시간</th>
<th>접속결과</th>
</tr>
</thead>
<tbody>
<tr v-for="(itm, indx) in resultMessage" :key="indx">
<td>{{ indx + 1 }}</td>
<td>{{ itm.time }}</td>
<td>{{ itm.message }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="modal-content-monthly" v-show="currentPage == 2">
<Splitter style="height: 100%; border: 0px solid #e5e7eb">
<SplitterPanel class="flex align-items-center justify-content-center" :size="20" :minSize="10">
<div class="content-box">
<div class="file-zone">
<div class="content-titleZone" style="height: 60px">
<p class="box-title">table 정보</p>
</div>
<div class="content-zone2">
<ul class="content-list" v-if="tableList.length > 0">
<li class="cursor" v-for="(item, indx) in tableList" :key="indx">
<a @click="getTableData(item)" :class="{
'file-list': true,
selected: selectTable === item,
}">
<div class="flex align-center">
<!-- <p>{{ item.tableNmKr != null && item.tableNmKr != '' ? item.tableNmKr : '-' }} <span style="opacity: .6;">({{ item.tableNm }})</span></p> -->
<p>{{ item.tableNmKr != null && item.tableNmKr != '' ? item.tableNmKr : item.tableNm }}</p>
</div>
</a>
</li>
</ul>
</div>
</div>
</div>
</SplitterPanel>
<SplitterPanel class="flex align-items-center justify-content-center" :size="80">
<div class="content-box">
<div class="content-titleZone" style="height: 60px">
<div class="flex justify-between aling-center">
<p class="box-title">쿼리 작업</p>
<div>
<button class="icon-btn" @click="executeQuery" title="실행">
<svg-icon type="mdi" :path="playPath" :color="'#fbbe28'"></svg-icon>
</button>
</div>
</div>
</div>
<div class="content-zone">
<Splitter style="height: 100%" layout="vertical">
<SplitterPanel class="flex align-items-center justify-content-center" :size="50" :minSize="20">
<textarea style="
resize: none;
max-width: 100%;
max-height: 100%;
padding: 10px;
" v-model="jobItm.itm.query"></textarea>
</SplitterPanel>
<SplitterPanel class="align-items-center justify-content-center" :size="50">
<ul class="tab-nav flex justify-start">
<li @click="showTab('tab1')">
<a href="#tab01" :class="{ activeTab: activeTab === 'tab1' }">작업결과</a>
</li>
<li @click="showTab('tab2')">
<a href="#tab02" :class="{ activeTab: activeTab === 'tab2' }">작업log</a>
</li>
</ul>
<div v-show="activeTab === 'tab1'" style="
height: calc(100% - 60px);
overflow: auto;
padding: 10px;
">
<div class="count-zone" v-if="jobItm.dataTable.columnDatas.length > 0">
<p> 총 <span>{{ jobItm.dataTable.totalRows }}</span>건 중 <span>{{ jobItm.dataTable.rowData.length }}</span>건 조회 </p>
</div>
<div class="table-zone">
<table class="list-table">
<!-- col 꼭 너비 기재해야함! 그래야 100%로 차지함 -->
<thead>
<tr v-if="jobItm.dataTable.columnDatas.length > 0">
<th v-for="(itm, indx) in jobItm.dataTable
.columnDatas" :key="indx" style="min-width: 150px !important"> {{ itm.columnNm }} <label class="check-label">
<input type="checkbox" class="custom-checkbox" v-model="itm.pkAt" />
</label>
</th>
</tr>
</thead>
<tbody v-if="jobItm.dataTable.rowData.length > 0">
<tr v-for="(row, rows) in jobItm.dataTable.rowData" :key="rows">
<td v-for="(itm, indx) in row" :key="indx" style="
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"> {{ itm }} </td>
</tr>
</tbody>
</table>
</div>
</div>
<div v-show="activeTab === 'tab2'" style="
height: calc(100% - 60px);
overflow: auto;
padding: 10px;
">
<div class="table-zone">
<table class="list-table">
<colgroup>
<col width="10%" />
<col width="10%" />
<col width="" />
<col width="10%" />
</colgroup>
<thead>
<tr>
<th>No</th>
<th>접속시간</th>
<th>접속결과</th>
<th>접속내용</th>
</tr>
</thead>
<tbody>
<tr v-for="(itm, indx) in executeMessage" :key="indx">
<td>{{ indx + 1 }}</td>
<td>{{ itm.time }}</td>
<td>{{ itm.message }}</td>
<td>{{ itm.result }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</SplitterPanel>
</Splitter>
</div>
</div>
</SplitterPanel>
</Splitter>
</div>
<div class="modal-end flex justify-end">
<button class="blue-border-btn small-btn" @click="setPage(1)" v-show="currentPage == 2">이전</button>
<button class="blue-border-btn small-btn" @click="setPage(2)" v-show="currentPage == 1" :disabled="!successAt">다음</button>
<button class="blue-btn small-btn" @click="handleSaveNodeData(jobItm)" v-show="currentPage == 2">확인</button>
<button class="blue-border-btn small-btn" @click="$emit('closePopup')">취소</button>
</div>
</div>
<DBConSearch :openPopup="openSearchModal" @modalclose="dbConSearchOpen" @selectItm="selectDbcon" />
</div>
</template>
<script>
import axios from "axios";
import SvgIcon from "@jamescoyle/vue-icon";
import DBConSearch from "../../dataComponent/DbConnectionSearchModal.vue";
import { mdiClose, mdiPlay, mdiCancel } from "@mdi/js";
export default {
name: "database-connection",
props: {
openPopup: {
type: Boolean,
default: false,
},
jobItem: {
type: Boolean,
default: null,
},
},
data() {
return {
closePath: mdiClose,
// 현재 모달창 관리
isModalOpen: this.openPopup,
// 연계정보 불러오기
openSearchModal: false,
// 커넥션 DB 오브젝트
jobItm: this.jobItem,
connectionDB: {},
linkConnectionDB: {},
inputConnectionDB: {},
resultMessage: [],
executeMessage: [],
// 연계 성공여부
successAt: false,
databaseTypeList: [],
currentPage: 1,
tableList: [],
selectTable: {},
activeTab: "tab1",
playPath: mdiPlay,
cancelPath: mdiCancel,
};
},
methods: {
// 화면전환
setPage: function (val) {
this.currentPage = val;
if (val == 2) {
this.getDbConnectionTableList();
}
},
handleSaveNodeData(jobItm) {
this.$emit('saveNodeData', jobItm);
this.$emit('closePopup');
},
/***************************************************접속정보 설정************************************************************************/
// 연계가능 여부 테스트
dataBaseConnectionCheck: function () {
var vm = this;
if (this.jobItm.itm_option_bool == true) {
this.jobItm.itm = this.linkConnectionDB;
} else {
this.jobItm.itm = this.inputConnectionDB;
}
this.jobItm.itm.loadAt = this.jobItm.itm_option_bool;
delete this.jobItm.itm.type;
axios({
url: "/data/dataBaseConnectionCheck.json",
method: "post",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
data: vm.jobItm.itm,
})
.then(function (response) {
if (response.data.checkMessage.success == true) {
vm.successAt = true;
} else {
vm.successAt = false;
}
vm.$showAlert("결과내용", response.data.checkMessage.message);
vm.resultMessage.push({
time: vm.$getFullTime(),
message: response.data.checkMessage.message,
result: response.data.checkMessage.success
? "접속성공"
: "접속실패",
});
})
.catch(function (error) { });
},
// db커넥션 선택창 호출
dbConSearchOpen: function (val) {
this.openSearchModal = val;
},
// 연계정보 받기
selectDbcon: function (dbcon) {
this.linkConnectionDB = dbcon;
},
/***************************************************접속정보 설정 끝*******************************************************************/
/***************************************************데이터 베이스 설정*******************************************************************/
// 탭 변경
showTab: function (tabName) {
this.activeTab = tabName;
},
//DB 접속 - 테이블 목록 조회
getDbConnectionTableList: function () {
let vm = this;
axios({
url: "/data/selectTableList.json",
method: "post",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
data: vm.jobItm.itm,
})
.then(function (response) {
if (response.data.checkMessage.success == true) {
vm.tableList = response.data.resultData.tableList;
}
})
.catch(function (error) { });
},
// 테이블 클릭
clickTable: function (itm) {
this.selectTable = itm;
},
// 선택한 테이블 정보 가져오기
getTableData: function (itm) {
let vm = this;
itm.perPage = this.jobItm.dataTable.perPage;
// 통신시 데이터 형문제로 삭제
this.jobItm.itm.creatDt = null;
let requestData = {
dataset: itm,
connectionDB: this.jobItm.itm,
};
axios({
url: "/data/getTableData.json",
method: "post",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
data: requestData,
})
.then(function (response) {
if (response.data.checkMessage.success) {
vm.jobItm.dataTable = response.data.resultData.dataTable;
vm.jobItm.itm.query = vm.jobItm.dataTable.query;
vm.columnDatas = response.data.resultData.dataTable.columnDatas;
vm.jobItm.front_dataTable.columnDatas = vm.columnDatas;
}
vm.executeMessage.push({
time: vm.$getFullTime(),
message: response.data.resultData.dataTable.checkMessage.message,
result: response.data.resultData.dataTable.checkMessage.success
? "성공"
: "실패",
});
})
.catch(function (error) { });
},
// 쿼리 실행
executeQuery: function () {
let vm = this;
// 통신시 데이터 형문제로 삭제
this.jobItm.itm.creatDt = null;
this.jobItm.dataTable.query = this.jobItm.itm.query;
let requestData = {
dataTable: this.jobItm.dataTable,
connectionDB: this.jobItm.itm,
};
axios({
url: "/data/getTableDataByQuery.json",
method: "post",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
data: requestData,
})
.then(function (response) {
if (response.data.checkMessage.success) {
vm.jobItm.dataTable = response.data.resultData.dataTable;
vm.jobItm.itm.query = vm.jobItm.dataTable.query;
}
vm.executeMessage.push({
time: vm.$getFullTime(),
message: response.data.resultData.dataTable.checkMessage.message,
result: response.data.resultData.dataTable.checkMessage.success
? "성공"
: "실패",
});
})
.catch(function (error) { });
},
/***************************************************데이터 베이스 설정끝*******************************************************************/
// 초기화 function
init: async function () {
this.databaseTypeList = await this.$getDataBaseTypeList();
if (this.jobItm == null) {
this.jobItm = Object.assign({}, this.$getDefaultJobGroup().node);
this.linkConnectionDB = Object.assign(
{},
this.$getDefaultJobGroup().connectionDb
);
this.inputConnectionDB = Object.assign(
{},
this.$getDefaultJobGroup().connectionDb
);
this.jobItm.itm = Object.assign(
{},
this.$getDefaultJobGroup().connectionDb
);
} else {
if (this.jobItm.itm_option_bool) {
this.linkConnectionDB = this.jobItm.itm;
this.connectionDB = this.linkConnectionDB;
} else {
this.inputConnectionDB = this.jobItm.itm;
this.connectionDB = this.inputConnectionDB;
}
}
if (this.inputConnectionDB.databaseType == null) {
this.inputConnectionDB.databaseType = this.databaseTypeList.MARIADB.key;
}
},
},
watch: {
openPopup: function (v) {
this.isModalOpen = v;
},
jobItem: function (v) {
this.jobItm = v;
if (v.itm_option_bool) {
this.linkConnectionDB = this.jobItm.itm;
} else {
this.inputConnectionDB = this.jobItm.itm;
}
},
},
components: {
DBConSearch: DBConSearch,
SvgIcon: SvgIcon,
},
mounted() {
this.init();
},
create() {
if (this.jobItm == null) {
this.jobItm = Object.assign({}, this.defaultJobItm);
this.jobItm.itm = this.$getDefaultJobGroup().connectionDb;
}
},
};
</script>
<style>
.content-zone2 {
height: calc(100% - 57px);
/* 기존 스타일 유지 */
max-height: calc(100% - 57px);
/* 최대 높이 설정 */
overflow-y: auto;
/* 수직 스크롤 추가 */
overflow-x: hidden;
/* 수평 스크롤 숨기기 (원하는 경우) */
}
</style>