박정하 박정하 04-28
250428 박정하 데이터 활용 수정
@ffb97d77f38d75adc67163fb0bb88b5c58f2c94d
client/views/component/SplitterLayout.vue
--- client/views/component/SplitterLayout.vue
+++ client/views/component/SplitterLayout.vue
@@ -1,8 +1,8 @@
 <template>
-  <Splitter :class="{ 'content-box': true, active: !$isEmpty(selectLayout) && splitInfo.layout_nm == selectLayout.layout_nm }" :layout="splitInfo.layout_type" @resizeend="updateSizes" @Click.stop="clickLayout(splitInfo)">
+  <Splitter :class="{ 'content-box': true, active: !$isEmpty(selectLayout) && splitInfo.layout_nm == selectLayout.layout_nm }" :layout="splitInfo.layout_type" @resizeend="updateSizes" @Click.stop="onChange(splitInfo)">
     <SplitterPanel class="content-box padding-1" v-if="splitInfo.children.length < 1" :style="$createStyleSheet(splitInfo.styleSheet)">
       <ComponentTitle v-if="splitInfo.useSj" :title="splitInfo.layoutSj" />
-      <BaseComponent v-else-if="splitInfo.se == 'component'" :component="splitInfo.component" @onChange="onChange" @Click.stop="clickLayout(splitInfo)" />
+      <BaseComponent v-if="splitInfo.se == 'component'" :component="splitInfo.component" @onChange="onChange" @Click.stop="onChange(splitInfo)" />
     </SplitterPanel>
     <template v-else>
       <SplitterPanel class="content-box" v-for="(item, idx) of splitInfo.children" :key="idx" :style="$createStyleSheet(splitInfo.styleSheet)">
@@ -31,9 +31,6 @@
       this.splitInfo["layout_size1"] = newSizes.sizes[0];
       this.splitInfo["layout_size2"] = newSizes.sizes[1];
       this.splitInfo["sizes"] = newSizes.sizes;
-    },
-    clickLayout: function (splitInfo) {
-      this.$emit("onChange", splitInfo);
     },
     onChange: function (layout) {
       this.$emit("onChange", layout);
client/views/component/connection/itm/dataFilter.vue
--- client/views/component/connection/itm/dataFilter.vue
+++ client/views/component/connection/itm/dataFilter.vue
@@ -1,270 +1,241 @@
 <template>
   <div v-show="isModalOpen" class="modal-wrapper">
-    <div class="modal-container" style="height: auto">
-      <div class="modal-title">
-        <div class="flex justify-between align-center">
-          <h2>데이터 필터</h2>
-          <button class="close-btn" @click="closeModal">
-            <svg-icon
-              type="mdi"
-              :width="20"
-              :height="20"
-              :path="closePath"
-            ></svg-icon>
-          </button>
-        </div>
+    <div class="modal-container">
+      <div class="modal-title flex justify-between align-center">
+        <h2>데이터베이스 읽기</h2>
+        <button class="close-btn" @click="closeModal">
+          <svg-icon type="mdi" :width="20" :height="20" :path="closePath"></svg-icon>
+        </button>
       </div>
-      <div class="modal-content-monthly">
-        <div class="input-container flex">
-          <label class="radio-label">
-            <input
-              type="radio"
-              :name="comId + 'match'"
-              class="custom-radiobox"
-              :value="true"
-              v-model="item.itm.match_type"
-            />
-            <span>AND 연산</span>
-          </label>
-          <label class="radio-label">
-            <input
-              type="radio"
-              :name="comId + 'match'"
-              class="custom-radiobox"
-              :value="false"
-              v-model="item.itm.match_type"
-            />
-            <span>OR 연산</span>
-          </label>
-        </div>
+    </div>
+    <div class="modal-content-monthly">
+      <template v-if="currentPage == 1">
         <div class="table-zone">
           <table class="form-table">
-            <!-- col 꼭 너비 기재해야함! 그래야 100%로 차지함 -->
             <colgroup>
               <col style="width: 25%" />
-              <col style="width: 25%" />
-              <col style="width: 25%" />
-              <col style="width: 25%" />
+              <col style="width: 75%" />
             </colgroup>
-            <thead>
+            <tbody v-if="jobItm.itm != null">
               <tr>
-                <th>컬럼</th>
-                <th>연산</th>
-                <th>내용</th>
-                <th>관리</th>
+                <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>
-            </thead>
-            <tbody>
-              <tr v-for="(filter, indx) in item.itm.filterItems" :key="indx">
+              <tr v-show="jobItm.itm_option_bool">
+                <th>연계정보</th>
                 <td>
-                  <select
-                    class="full-input"
-                    style="width: 100%"
-                    @change="dataInsert($event, filter)"
-                    v-model="filter.coulmn_nm"
-                  >
-                    <option
-                      v-for="(temp, indxc) in item.front_dataTable.columnDatas"
-                      :key="indxc"
-                      :value="temp.orginlColumnNm"
-                    >
-                      {{ temp.displyColumnNm }}
-                    </option>
+                  <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>
-                  <select
-                    class="full-input"
-                    style="width: 100%"
-                    v-model="filter.calc_ty"
-                  >
-                    <option value="1">=</option>
-                    <option
-                      v-if="getDataType(indx, filter.coulmn_nm) != 'STRING'"
-                      value="2"
-                    >
-                      &lt;
-                    </option>
-                    <option
-                      v-if="getDataType(indx, filter.coulmn_nm) != 'STRING'"
-                      value="3"
-                    >
-                      &gt;
-                    </option>
-                    <option
-                      v-if="getDataType(indx, filter.coulmn_nm) != 'STRING'"
-                      value="4"
-                    >
-                      &lt;=
-                    </option>
-                    <option
-                      v-if="getDataType(indx, filter.coulmn_nm) != 'STRING'"
-                      value="5"
-                    >
-                      &gt;=
-                    </option>
-                    <option value="6">!=</option>
-                    <option
-                      v-if="getDataType(indx, filter.coulmn_nm) == 'STRING'"
-                      value="7"
-                    >
-                      포함
-                    </option>
-                  </select>
+                  <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
-                    :type="setDataType(indx, filter.coulmn_nm)"
-                    style="width: 100%"
-                    v-model="filter.cmpr_value"
-                  />
+                  <input id="conectPort" type="text" @input="successAt = false" class="half-input" v-model="inputConnectionDB.conectPort" :disabled="jobItm.itm_option_bool" />
                 </td>
-                <td style="text-align: center">
-                  <button
-                    class="green-border-btn small-btn"
-                    @click="deleteFilter(indx)"
-                  >
-                    삭제
-                  </button>
+              </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>
-      </div>
-      <div class="modal-end flex justify-end">
-        <button class="gray-btn small-btn" @click="closeModal">닫기</button>
-        <button class="green-btn small-btn" @click="addFiter">필터추가</button>
-      </div>
+        <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>
+      </template>
+      <template v-if="currentPage == 2">
+        <div class="flex content-box" style="min-height: 60dvh; flex-wrap: nowrap;">
+          <div class="content-box pd10" style="width: 20%;">
+            <div class="content-titleZone flex justy justify-between align-center" style="height: 45px">
+              <p class="box-title">데이터베이스 정보</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 : item.tableNm }} </p>
+                    </div>
+                  </a>
+                </li>
+              </ul>
+            </div>
+          </div>
+          <div class="content-box" style="width: 80%;">
+            <div class="flex-column">
+              <div class="content-box pd10" style="height: 50%;">
+                <div class="content-titleZone flex justy justify-between align-center" style="height: 45px">
+                  <p class="box-title">쿼리 작업</p>
+                  <button class="icon-btn" @click="executeQuery" title="실행">
+                    <svg-icon type="mdi" :path="playPath" :color="'#fbbe28'"></svg-icon>
+                  </button>
+                </div>
+                <div class="flex" style="height: calc(100% - 60px)">
+                  <textarea style="resize: none; width: 100%; height: 100%; padding: 10px;" v-model="jobItm.itm.query"></textarea>
+                </div>
+              </div>
+              <div class="content-box pd10" style="height: 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'" class="content-box" style="height: calc(100% - 45px); padding: 10px;">
+                  <div class="count-zone mb10" v-if="jobItm.dataTable.columnDatas.length > 0">
+                    <p> 총 <span>{{ jobItm.dataTable.totalRows }}</span>건 중 <span>{{ jobItm.dataTable.rowData.length }}</span>건 조회 </p>
+                  </div>
+                  <div style="height: calc(100% - 15px); overflow: auto;">
+                    <table class="list-table" v-if="jobItm.dataTable.columnDatas.length > 0">
+                      <thead>
+                        <tr>
+                          <th v-for="(itm, indx) in jobItm.dataTable.columnDatas" :key="indx" style="min-width: 150px !important">
+                            <label class="check-label">
+                              <span class="mr10">{{ itm.columnNm }}</span>
+                              <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'" class=" content-box" style="height: calc(100% - 45px); padding: 10px;">
+                  <div style="height: calc(100% - 15px); overflow: auto;">
+                    <table class="list-table">
+                      <colgroup>
+                        <col width="10%" />
+                        <col width="60%" />
+                        <col width="20%" />
+                        <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.message }}</td>
+                          <td>{{ itm.time }}</td>
+                          <td>{{ itm.result }}</td>
+                        </tr>
+                      </tbody>
+                    </table>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </template>
     </div>
+    <DBConSearch :openPopup="openSearchModal" @modalclose="dbConSearchOpen" @selectItm="selectDbcon" />
   </div>
 </template>
-
 <script>
+// icon용 svg import
+import SvgIcon from "@jamescoyle/vue-icon";
+import { mdiMagnify, mdiClose } from "@mdi/js";
+
 export default {
-  name: "data-check",
-  props: {
-    openPopup: {
-      type: Boolean,
-      default: false,
-    },
-    item: {
-      type: Object,
-    },
-    saveNodeData: {
-      type: Function,
-    },
-  },
+  components: { SvgIcon },
+
   data() {
     return {
-      comId:
-        "comId_" +
-        Math.random().toString(36).substring(2, 15) +
-        Math.random().toString(36).substring(2, 15),
-      isModalOpen: this.openPopup,
-      itm: this.item,
-    };
-  },
-  methods: {
-    // 모달 닫기
-    closeModal: function () {
-      this.isModalOpen = false;
-      this.$emit("closePopup", this.item);
-      this.$emit("closePopup2", this.item.id);
-    },
+      // icon용 svg path
+      searchPath: mdiMagnify,
+      closePath: mdiClose,
 
-    dataInsert: function (event, filter) {
-      for (var i = 0; i < this.item.front_dataTable.columnDatas.length; i++) {
-        if (
-          this.item.front_dataTable.columnDatas[i].orginlColumnNm ==
-          event.target.value
-        ) {
-          filter.coulmn_nm =
-            this.item.front_dataTable.columnDatas[i].orginlColumnNm;
-          filter.data_ty = this.item.front_dataTable.columnDatas[i].dataTy;
-        }
-      }
-    },
+      isModalOpen: true,
 
-    // 데이터 형반환
-    getDataType: function (index, coulmnNm) {
-      for (var i = 0; i < this.item.front_dataTable.columnDatas.length; i++) {
-        if (
-          this.item.front_dataTable.columnDatas[i].displyColumnNm == coulmnNm
-        ) {
-          return this.item.front_dataTable.columnDatas[i].dataTy;
-        }
-      }
-    },
-
-    // 데이터 타입체크
-    setDataType: function (index, coulmnNm) {
-      for (var i = 0; i < this.item.front_dataTable.columnDatas.length; i++) {
-        if (
-          this.item.front_dataTable.columnDatas[i].orginlColumnNm == coulmnNm
-        ) {
-          if (this.item.front_dataTable.columnDatas[i].dataTy == "STRING") {
-            return "text";
-          } else if (
-            this.item.front_dataTable.columnDatas[i].datadataTyType == "DATE"
-          ) {
-            return "date";
-          } else if (
-            this.item.front_dataTable.columnDatas[i].dataTy == "DATETIME"
-          ) {
-            return "datetime-local";
-          } else if (
-            this.item.front_dataTable.columnDatas[i].dataTy == "LONG"
-          ) {
-            return "number";
-          } else {
-            return "number";
-          }
-        }
-      }
-    },
-
-    // 필터추가
-    addFiter: function () {
-      const item = JSON.parse(
-        JSON.stringify(this.$getDefaultJobGroup().filterItem)
-      );
-
-      if (
-        this.item.front_dataTable.columnDatas == null ||
-        this.item.front_dataTable.columnDatas.length == 0
-      ) {
-        this.$showAlert("경고", "데이터 컬럼이 없습니다.");
-        return;
-      } else {
-        item.coulmn_nm =
-          this.item.front_dataTable.columnDatas[0].orginlColumnNm;
-        item.data_ty = this.item.front_dataTable.columnDatas[0].dataTy;
-        item.calc_ty = 1;
-        item.indx = this.item.itm.filterItems.length + 1;
-        item.cmpr_value = "";
-      }
-
-      this.item.itm.filterItems.push(item);
-    },
-    // 필터 삭제
-    deleteFilter: function (indx) {
-      this.item.itm.filterItems.splice(indx, 1);
-    },
-  },
-  watch: {
-    openPopup: function (v) {
-      this.isModalOpen = v;
-    },
-
-    item: function (v) {
-      //this.itm = v;
-      
-    },
-  },
-  computed: {},
-  components: {},
-  mounted() {
-  },
-};
+      search: Object.assign({}, this.$getDefaultSerchVO()),
+      searchData: this.$getDefaultSerchItem(null, "string"),
+    }
+  }
+}
 </script>
(파일 끝에 줄바꿈 문자 없음)
client/views/component/flowComponent/JobGroupManagement.vue
--- client/views/component/flowComponent/JobGroupManagement.vue
+++ client/views/component/flowComponent/JobGroupManagement.vue
@@ -2,7 +2,7 @@
   <div class="flex-column">
     <div class="content-titleZone flex justify-between align-center">
       <p class="box-title">잡그룹 목록</p>
-      <button class="blue-border-btn small-btn" @click="fnOpenModal"> 아이템 추가 </button>
+      <button class="blue-border-btn small-btn" @click="fnOpenModal">추가</button>
     </div>
     <div class="data-list">
       <template v-for="(item, idx) in currentJobGroup.jobItms" :key="idx">
@@ -16,8 +16,8 @@
               <p class="ml10"> ({{ item.dataTable.columnDatas.length > 0 ? "설정 완료" : "미설정" }}) </p>
             </div>
             <div>
-              <button type="button" class="blue-border-btn set-btn" @click="fnOpenSetup(item, idx)"> 수정 </button>
-              <button type="button" class="red-border-btn set-btn" @click="fnDeleteItem(item)"> 삭제 </button>
+              <button type="button" class="blue-border-btn set-btn" @click="fnOpenSetup(item, idx)">수정</button>
+              <button type="button" class="red-border-btn set-btn" @click="fnDeleteItem(item)">삭제</button>
             </div>
           </div>
         </div>
@@ -85,10 +85,6 @@
       isOpenSetupModal: false,
     };
   },
-
-  created() { },
-
-  mounted() { },
 
   watch: {
     jobGroup: {
@@ -162,8 +158,7 @@
       let typeArr = item.type.split("_");
       if (typeArr[typeArr.length - 1] == "FILTER") {
         this.frontNodes = []; // 초기화
-        this.frontNodes.push(this.currentJobGroup.jobItms[idx - 1]);
-
+        this.frontNodes.push({ jobItm: this.currentJobGroup.jobItms[idx - 1] });
         if (this.frontNodes.length < 1) {
           this.$showAlert("경고", "선행 노드가 없습니다.");
           return;
@@ -184,7 +179,6 @@
 
     // 잡아이템설정 저장
     fnSaveSetup(jobItem) {
-      
       this.currentJobGroup.jobItms[this.currentJobItmIdx] = jobItem;
       this.fnCloseSetup(); // 노드설정 모달 닫기
     },
 
client/views/component/modal/connection/DbReadModal.vue (deleted)
--- client/views/component/modal/connection/DbReadModal.vue
@@ -1,593 +0,0 @@
-<template>
-  <div class="modal-wrapper">
-    <div class="modal-container large-modal">
-      <div class="modal-title flex justify-between align-center">
-        <h2>데이터베이스 읽기</h2>
-        <button class="close-btn" @click="$emit('onClose')">
-          <svg-icon type="mdi" :width="20" :height="20" :path="closePath"></svg-icon>
-        </button>
-      </div>
-      <div class="modal-content-monthly">
-        <!-- 페이지 1: 데이터베이스 연결 설정 -->
-        <template v-if="currentPage == 1">
-          <!-- 데이터베이스 정보 -->
-          <div class="content-titleZone flex justy justify-between align-center">
-            <p class="box-title">데이터베이스 정보</p>
-          </div>
-          <table class="form-table">
-            <colgroup>
-              <col style="width: 20%" />
-              <col style="width: 80%" />
-            </colgroup>
-            <tbody>
-              <tr>
-                <th>연계정보 타입</th>
-                <td>
-                  <div class="input-container flex">
-                    <label class="radio-label">
-                      <input type="radio" name="radio" :value="false" class="custom-radiobox" @change="onConnectionTypeChange(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="onConnectionTypeChange(true)" 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="getConnectionDisplayText()" />
-                  <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="currentConnectionDB.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="currentConnectionDB.conectIp" placeholder="ex. 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="currentConnectionDB.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="currentConnectionDB.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="currentConnectionDB.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="currentConnectionDB.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="70%" />
-                <col width="20%" />
-              </colgroup>
-              <thead>
-                <tr>
-                  <th>No</th>
-                  <th>접속결과</th>
-                  <th>접속시간</th>
-                </tr>
-              </thead>
-              <tbody>
-                <tr v-for="(itm, idx) in resultMessage" :key="idx">
-                  <td>{{ idx + 1 }}</td>
-                  <td>{{ itm.message }}</td>
-                  <td>{{ itm.time }}</td>
-                </tr>
-              </tbody>
-            </table>
-          </div>
-        </template>
-        <!-- 페이지 2: 쿼리 관리 -->
-        <template v-if="currentPage == 2">
-          <div class="flex content-box" style="min-height: 60dvh; flex-wrap: nowrap;">
-            <div class="content-box pd10" style="width: 20%;">
-              <div class="content-titleZone flex justy justify-between align-center" style="height: 45px">
-                <p class="box-title">데이터베이스 정보</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>{{ getTableDisplayName(item) }}</p>
-                      </div>
-                    </a>
-                  </li>
-                </ul>
-              </div>
-            </div>
-            <div class="content-box" style="width: 80%;">
-              <div class="flex-column">
-                <div class="content-box pd10" style="height: 50%;">
-                  <div class="content-titleZone flex justy justify-between align-center" style="height: 45px">
-                    <p class="box-title">쿼리 작업</p>
-                    <button class="icon-btn" @click="executeQuery" title="실행">
-                      <svg-icon type="mdi" :path="playPath" :color="'#fbbe28'"></svg-icon>
-                    </button>
-                  </div>
-                  <div class="flex" style="height: calc(100% - 60px)">
-                    <textarea style="resize: none; width: 100%; height: 100%; padding: 10px;" v-model="jobItm.itm.query"></textarea>
-                  </div>
-                </div>
-                <div class="content-box pd10" style="height: 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'" class="content-box" style="height: calc(100% - 45px); padding: 10px;">
-                    <div class="count-zone mb10" v-if="jobItm.dataTable.columnDatas.length > 0">
-                      <p>총 <span>{{ jobItm.dataTable.totalRows }}</span>건 중 <span>{{ jobItm.dataTable.rowData.length }}</span>건 조회</p>
-                    </div>
-                    <div style="height: calc(100% - 15px); overflow: auto;">
-                      <table class="list-table">
-                        <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'" class=" content-box" style="height: calc(100% - 45px); padding: 10px;">
-                    <div style="height: calc(100% - 15px); overflow: auto;">
-                      <table class="list-table">
-                        <colgroup>
-                          <col width="10%" />
-                          <col width="60%" />
-                          <col width="20%" />
-                          <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.message }}</td>
-                            <td>{{ itm.time }}</td>
-                            <td>{{ itm.result }}</td>
-                          </tr>
-                        </tbody>
-                      </table>
-                    </div>
-                  </div>
-                </div>
-              </div>
-            </div>
-          </div>
-        </template>
-      </div>
-      <!-- 모달 하단 버튼 영역 -->
-      <div class="modal-end flex justify-end">
-        <button class="blue-border-btn small-btn" v-if="currentPage == 2" @click="moveTo('prev')">이전</button>
-        <button class="blue-border-btn small-btn" v-if="currentPage == 1" @click="moveTo('next')">다음</button>
-        <button class="blue-btn small-btn" v-if="isDataSet" @click="fnSave">등록</button>
-        <button class="blue-border-btn small-btn" @click="$emit('onClose')">취소</button>
-      </div>
-    </div>
-  </div>
-  <DBConSearch :openPopup="openSearchModal" @modalclose="dbConSearchOpen" @selectItm="selectDbcon" />
-</template>
-<script>
-import _ from "lodash";
-import axios from "axios";
-
-// icon용 svg import
-import SvgIcon from "@jamescoyle/vue-icon";
-import { mdiMagnify, mdiClose, mdiPlay } from "@mdi/js";
-
-// 컴포넌트
-import DBConSearch from "../../dataComponent/DbConnectionSearchModal.vue";
-
-export default {
-  name: "DatabaseConnectionModal",
-
-  components: {
-    SvgIcon,
-    DBConSearch
-  },
-
-  props: {
-    currentJobItm: String,
-    jobItem: Object
-  },
-
-  data() {
-    return {
-      // icon용 svg path
-      searchPath: mdiMagnify,
-      closePath: mdiClose,
-      playPath: mdiPlay,
-
-      // 페이지 관련
-      currentPage: 1,
-      activeTab: "tab1",
-
-      // 상태 관리
-      successAt: false, // 연결 성공 여부
-      isDataSet: false, // 데이터 설정 여부 추가
-
-      // 데이터 객체들
-      jobItm: {
-        itm: null,
-        itm_option_bool: false,
-        dataTable: {
-          columnDatas: [],
-          rowData: [],
-          totalRows: 0,
-          perPage: 10,
-          query: ""
-        }
-      },
-
-      // 연계정보 관리
-      openSearchModal: false,
-      linkConnectionDB: {},
-      inputConnectionDB: {
-        databaseType: "",
-        conectIp: "",
-        conectPort: "",
-        databaseNm: "",
-        userId: "",
-        userPassword: ""
-      },
-      // 현재 표시되는 연결 정보 (직접입력/불러오기 모두 대응)
-      currentConnectionDB: {
-        databaseType: "",
-        conectIp: "",
-        conectPort: "",
-        databaseNm: "",
-        userId: "",
-        userPassword: ""
-      },
-
-      // 데이터 목록
-      databaseTypeList: [],
-      tableList: [],
-      selectTable: {},
-
-      // 로그 메시지
-      resultMessage: [],
-      executeMessage: []
-    };
-  },
-
-  watch: {
-    jobItem: {
-      handler(newVal) {
-        if (newVal) {
-          this.jobItm = _.cloneDeep(newVal);
-          if (this.jobItm.itm_option_bool) {
-            this.linkConnectionDB = this.jobItm.itm || {};
-            this.currentConnectionDB = _.cloneDeep(this.linkConnectionDB);
-          } else {
-            this.inputConnectionDB = this.jobItm.itm || {};
-            this.currentConnectionDB = _.cloneDeep(this.inputConnectionDB);
-          }
-        }
-      },
-      immediate: true
-    },
-  },
-
-  created() {
-    this.initializeComponent();
-  },
-
-  mounted() {
-    this.init();
-  },
-
-  methods: {
-    // 초기화 함수들
-    initializeComponent() {
-      if (!this.$isEmpty(this.currentJobItm)) {
-        let currentJobItm = JSON.parse(this.currentJobItm);
-        if (!this.$isEmpty(currentJobItm)) {
-          this.jobItm = _.cloneDeep(currentJobItm);
-        }
-      }
-
-      if (!this.jobItm.itm) {
-        this.jobItm.itm = _.cloneDeep(this.$getDefaultJobGroup().connectionDb || {});
-      }
-    },
-
-    async init() {
-      this.databaseTypeList = await this.$getDataBaseTypeList();
-
-      if (this.jobItm == null) {
-        this.jobItm = _.cloneDeep(this.$getDefaultJobGroup().node || {});
-        this.linkConnectionDB = _.cloneDeep(this.$getDefaultJobGroup().connectionDb || {});
-        this.inputConnectionDB = _.cloneDeep(this.$getDefaultJobGroup().connectionDb || {});
-        this.jobItm.itm = _.cloneDeep(this.$getDefaultJobGroup().connectionDb || {});
-      } else {
-        if (this.jobItm.itm_option_bool) {
-          this.linkConnectionDB = _.cloneDeep(this.jobItm.itm) || {};
-          this.currentConnectionDB = _.cloneDeep(this.linkConnectionDB);
-        } else {
-          this.inputConnectionDB = _.cloneDeep(this.jobItm.itm) || {};
-          this.currentConnectionDB = _.cloneDeep(this.inputConnectionDB);
-        }
-      }
-
-      if (!this.inputConnectionDB.databaseType && this.databaseTypeList.MARIADB) {
-        this.inputConnectionDB.databaseType = this.databaseTypeList.MARIADB.key;
-        if (!this.jobItm.itm_option_bool) {
-          this.currentConnectionDB.databaseType = this.databaseTypeList.MARIADB.key;
-        }
-      }
-    },
-
-    // 연결 타입 변경 시(직접입력/불러오기) 입력 필드 업데이트
-    onConnectionTypeChange(isImport) {
-      this.successAt = false;
-      if (isImport) {
-        // 불러오기 선택 시
-        this.currentConnectionDB = _.cloneDeep(this.linkConnectionDB);
-      } else {
-        // 직접입력 선택 시
-        this.currentConnectionDB = _.cloneDeep(this.inputConnectionDB);
-      }
-    },
-
-    // 유틸리티 함수들
-    getConnectionDisplayText() {
-      return this.linkConnectionDB.conectNm
-        ? `${this.linkConnectionDB.conectNm}(${this.linkConnectionDB.conectIp})`
-        : "";
-    },
-
-    getTableDisplayName(item) {
-      return item.tableNmKr && item.tableNmKr !== "" ? item.tableNmKr : item.tableNm;
-    },
-
-    // 데이터베이스 연결 관리
-    dataBaseConnectionCheck() {
-      if (this.jobItm.itm_option_bool) {
-        // 불러오기 모드일 때 linkConnectionDB 사용
-        this.jobItm.itm = _.cloneDeep(this.linkConnectionDB);
-      } else {
-        // 직접입력 모드일 때 currentConnectionDB에서 업데이트된 값 가져옴
-        this.inputConnectionDB = _.cloneDeep(this.currentConnectionDB);
-        this.jobItm.itm = _.cloneDeep(this.inputConnectionDB);
-      }
-
-      this.jobItm.itm.loadAt = this.jobItm.itm_option_bool;
-
-      if (this.jobItm.itm.type) {
-        delete this.jobItm.itm.type;
-      }
-
-      axios({
-        url: "/data/dataBaseConnectionCheck.json",
-        method: "post",
-        headers: { "Content-Type": "application/json; charset=UTF-8" },
-        data: this.jobItm.itm
-      })
-        .then(response => {
-          const checkMessage = response.data.checkMessage || {};
-          this.successAt = checkMessage.success === true;
-          this.$emit("onDfltSetChange", checkMessage.success);
-          this.$showAlert("결과내용", checkMessage.message);
-
-          this.resultMessage.push({
-            time: this.$getFullTime(),
-            message: checkMessage.message,
-            result: checkMessage.success ? "접속성공" : "접속실패"
-          });
-        })
-        .catch(error => {
-          console.error("Database connection check error:", error);
-          this.successAt = false;
-          this.$emit("onDfltSetChange", false);
-        });
-    },
-
-    // 연계정보 관리
-    dbConSearchOpen(val) {
-      this.openSearchModal = val;
-    },
-
-    selectDbcon(dbcon) {
-      this.linkConnectionDB = _.cloneDeep(dbcon);
-      // 불러오기 모드이면 현재 표시되는 필드 업데이트
-      if (this.jobItm.itm_option_bool) {
-        this.currentConnectionDB = _.cloneDeep(this.linkConnectionDB);
-      }
-    },
-
-    getTableData(item) {
-      this.selectTable = item;
-
-      const requestData = {
-        dataset: { ...item, perPage: this.jobItm.dataTable.perPage },
-        connectionDB: { ...this.jobItm.itm, creatDt: null }
-      };
-
-      axios({
-        url: "/data/getTableData.json",
-        method: "post",
-        headers: { "Content-Type": "application/json; charset=UTF-8" },
-        data: requestData
-      })
-        .then(response => {
-          if (response.data.checkMessage.success) {
-            this.jobItm.dataTable = response.data.resultData.dataTable;
-            this.jobItm.itm_id = this.jobItm.itm.dbConectId;
-            this.jobItm.itm.query = this.jobItm.dataTable.query;
-            this.isDataSet = true;
-          } else {
-            this.isDataSet = false;
-          }
-
-          const checkMessage = response.data.resultData.dataTable.checkMessage || {};
-          this.executeMessage.push({
-            time: this.$getFullTime(),
-            message: checkMessage.message,
-            result: checkMessage.success ? "성공" : "실패"
-          });
-        })
-        .catch(error => {
-          console.error("Get table data error:", error);
-          this.isDataSet = false;
-        });
-    },
-
-    executeQuery() {
-      const requestData = {
-        dataTable: {
-          ...this.jobItm.dataTable,
-          query: this.jobItm.itm.query
-        },
-        connectionDB: {
-          ...this.jobItm.itm,
-          creatDt: null
-        }
-      };
-
-      axios({
-        url: "/data/getTableDataByQuery.json",
-        method: "post",
-        headers: { "Content-Type": "application/json; charset=UTF-8" },
-        data: requestData
-      })
-        .then(response => {
-          if (response.data.checkMessage.success) {
-            this.jobItm.dataTable = response.data.resultData.dataTable;
-            this.jobItm.itm_id = this.jobItm.itm.dbConectId;
-            this.jobItm.itm.query = this.jobItm.dataTable.query;
-            this.isDataSet = true;
-          } else {
-            this.isDataSet = false;
-          }
-
-          const checkMessage = response.data.resultData.dataTable.checkMessage || {};
-          this.executeMessage.push({
-            time: this.$getFullTime(),
-            message: checkMessage.message,
-            result: checkMessage.success ? "성공" : "실패"
-          });
-        })
-        .catch(error => {
-          console.error("Execute query error:", error);
-          this.isDataSet = false;
-        });
-    },
-
-    showTab(tabName) {
-      this.activeTab = tabName;
-    },
-
-    moveTo(type) {
-      if (type === 'prev') {
-        this.currentPage = 1;
-        this.tableList = []; // 초기화
-        this.jobItm.dataTable = {
-          columnDatas: [],
-          rowData: [],
-          totalRows: 0,
-          perPage: 10,
-          query: ""
-        }; // 초기화
-      } else if (type === 'next') {
-        if (!this.successAt) {
-          this.$showAlert("경고", "접속에 성공한 경우에만 진행할 수 있습니다.");
-        } else {
-          this.getDbConnectionTableList(); // 테이블 및 쿼리 관리
-        }
-      } else {
-        this.$showAlert("오류", "올바르지 않은 요청입니다.");
-      }
-    },
-
-    // 테이블 및 쿼리 관리
-    getDbConnectionTableList() {
-      axios({
-        url: "/data/selectTableList.json",
-        method: "post",
-        headers: { "Content-Type": "application/json; charset=UTF-8" },
-        data: this.jobItm.itm
-      })
-        .then(response => {
-          if (response.data.checkMessage.success) {
-            this.tableList = response.data.resultData.tableList || [];
-            this.currentPage = 2;
-          }
-        })
-        .catch(error => {
-          console.error("Get table list error:", error);
-          this.tableList = [];
-        });
-    },
-
-    // 저장
-    fnSave() {
-      this.$emit("onSave", this.jobItm);
-    }
-  }
-};
-</script>
-<style>
-.content-zone2 {
-  height: calc(100% - 57px);
-  max-height: calc(100% - 57px);
-  overflow-y: auto;
-  overflow-x: hidden;
-}
-</style>(파일 끝에 줄바꿈 문자 없음)
Add a comment
List