vue + jpa project (23) - 공통코드 상세코드관리(2) 본문

프로그램/Vue.js

vue + jpa project (23) - 공통코드 상세코드관리(2)

반응형

지난번 장에서는 백엔드 쪽을 작성해보았다.

 

이번엔 프론트엔드 소스를 작성해보겠다.

이것 역시 기존 그룹코드에서 했던 것과 유사하지만 리마인드 하면서 진행하겠다.

 

상세코드는 그룹코드와 달리 그룹코드 리스트에서 하나의 그룹코드를 가지고 출발하고 

그룹코드 별 상세코드를 관리하도록 한다. (상위 메뉴에 추가되지 않는다)

 

폴더는 그룹코드와 동일하게 src/views/code 로 하고 그 하위에 파일을 추가한다.

 

1. 공통코드 상세 리스트

  CodeDetailList.vue 파일

 

<template>
  <div class="board-list">
    <div class="common-buttons">
      <button type="button" class="w3-button w3-round w3-blue-gray" v-on:click="fnGroupList()">상위그룹</button>&nbsp;
      <button type="button" class="w3-button w3-round w3-blue-gray" v-on:click="fnWrite(`${groupCode}`)">등록</button>
    </div>
    <table class="w3-table-all">
      <thead>
      <tr>
        <th>No</th>
        <th>그룹코드</th>
        <th>상세코드값</th>
        <th>상세코드명</th>
        <th>순번</th>
        <th>사용여부</th>
        <th>등록일시</th>
      </tr>
      </thead>
      <tbody>

        <tr v-if="!list || (Array.isArray(list) && list.length ===0)">
          <td colspan="7">
            등록된 게시물이 없습니다.
          </td>
        </tr>

        <tr v-else v-for="(row, no) in list" :key="no">
          <td>{{ (this.page - 1)*size + (no+1) }}</td>
          <td>{{ row.group_code }}</td>
          <td>{{ row.code_value }}</td>
          <td><a v-on:click="fnView(`${row.group_code}`, `${row.code_value}`)">{{ row.code_name }}</a></td>
          <td>{{ row.sort_seq }}</td>
          <td>{{ row.use_yn }}</td>
          <td>{{ row.reg_date }}</td>
        </tr>
      </tbody>
    </table>
    <div class="pagination w3-bar w3-padding-16 w3-small" v-if="paging.total_list_cnt > 0">
      <span class="pg">
      <a href="javascript:;" @click="fnPage(1)" class="first w3-button w3-border">&lt;&lt;</a>
      <a href="javascript:;" v-if="paging.start_page > 10" @click="fnPage(`${paging.start_page-1}`)"
         class="prev w3-button w3-border">&lt;</a>
      <template v-for=" (n,index) in paginavigation()">
          <template v-if="paging.page==n">
              <strong class="w3-button w3-border w3-green" :key="index">{{ n }}</strong>
          </template>
          <template v-else>
              <a class="w3-button w3-border" href="javascript:;" @click="fnPage(`${n}`)" :key="index">{{ n }}</a>
          </template>
      </template>
      <a href="javascript:;" v-if="paging.total_page_cnt > paging.end_page"
         @click="fnPage(`${paging.end_page+1}`)" class="next w3-button w3-border">&gt;</a>
      <a href="javascript:;" @click="fnPage(`${paging.total_page_cnt}`)" class="last w3-button w3-border">&gt;&gt;</a>
      </span>
    </div>
  </div>
</template>

<script>
export default {
  data() { //변수생성
    return {
      requestBody: {}, //리스트 페이지 데이터전송
      list: {}, //리스트 데이터
      groupCode : this.$route.query.groupCode ? this.$route.query.groupCode : '',
      paging: {
        block: 0,
        end_page: 0,
        next_block: 0,
        page: 0,
        page_size: 0,
        prev_block: 0,
        start_index: 0,
        start_page: 0,
        total_block_cnt: 0,
        total_list_cnt: 0,
        total_page_cnt: 0,
      }, //페이징 데이터
      page: this.$route.query.page ? this.$route.query.page : 1,  // 기본페이지는 1페이지
      size: this.$route.query.size ? this.$route.query.size : 10, // 보여지는 리스트 사이즈 10개
      search_key: this.$route.query.search_key ? this.$route.query.search_key : '',
      search_value: this.$route.query.search_value ? this.$route.query.search_value : '',
      paginavigation: function () { //페이징 처리 for문 커스텀
        let pageNumber = [] //;
        let start_page = this.paging.start_page;
        let end_page = this.paging.end_page;
        for (let i = start_page; i <= end_page; i++) pageNumber.push(i);
        return pageNumber;
      }
    }
  },
  mounted() {
    this.fnGetList()
  },
  methods: {
    fnGetList() {
      this.requestBody = { // 데이터 전송
        groupCode : this.groupCode,
        useYn : 'Y',
        page: this.page,
        size: this.size
      }

      this.$axios.get(this.$serverUrl + "/codedetails/list_paging", {
        params: this.requestBody,
        headers: {}
      }).then((res) => {

        this.list = res.data.data
        this.paging = res.data.pagination

      }).catch((err) => {
        if (err.message.indexOf('Network Error') > -1) {
          alert('네트워크가 원활하지 않습니다.\n잠시 후 다시 시도해주세요.')
        }
      })
    },
    fnView(groupCode, codeValue) {
      this.requestBody.groupCode = groupCode
      this.requestBody.codeValue = codeValue
      this.$router.push({
        path : './detail',
        query: this.requestBody
      })
    },
    fnWrite(groupCode) {
      this.requestBody.groupCode = groupCode
      this.$router.push({
        path : './write',
        query: this.requestBody
      })
    },
    fnPage(n) {
      if(this.page !== n) {
        this.page = n
      }
      this.fnGetList()
    },
    fnGroupList() {

      this.requestBody = { // 데이터 전송
        useYn : 'Y',
        page: 1,
        size: 10
      }

      this.$router.push({
        path : '/codegroup/list',
        query: this.requestBody
      })
    }
  }
}
</script>

 

조회되는 항목만 다르고 사용여부가 'Y' 인 것만 조회되도록 강제한 것 이외에는 다른 부분이 많이 없다.

 

2. 공통코드 상세 등록

  CodeDetailWrite.vue 파일

<template>
  <div class="board-detail">
    <div class="common-buttons">
      <button type="button" class="w3-button w3-round w3-blue-gray" v-on:click="fnSave">저장</button>&nbsp;
      <button type="button" class="w3-button w3-round w3-gray" v-on:click="fnList">목록</button>
    </div>
    <div class="board-content">
      <input type="text" v-model="groupCode" class="w3-input w3-border" readonly>
      <input v-if="regDate === undefined || regDate === ''" maxlength="3" type="text" v-model="codeValue" class="w3-input w3-border" placeholder="상세코드값을 입력해주세요." style="ime-mode:disabled; text-transform:uppercase; ">
      <input v-if="regDate !== undefined && regDate !== ''" type="text" v-model="codeValue" class="w3-input w3-border" readonly>
      <input type="text" v-model="codeName" class="w3-input w3-border" placeholder="상세코드명을 입력해주세요.">
    </div>
    <div class="board-content">
      <input type="text" v-model="sortSeq" class="w3-input w3-border" placeholder="정렬순번을 입력해주세요.">
    </div>
    <div class="board-content">
      <select v-model="useYn">
        <option value="Y">Y</option>
        <option value="N">N</option>
      </select>
    </div>

    <div class="common-buttons">
      <button type="button" class="w3-button w3-round w3-blue-gray" v-on:click="fnSave">저장</button>&nbsp;
      <button type="button" class="w3-button w3-round w3-gray" v-on:click="fnList">목록</button>
    </div>
  </div>
</template>


<script>
export default {

  data() {
    return {
      requestBody : this.$route.query,
      groupCode : this.$route.query.groupCode,
      codeValue : this.$route.query.codeValue,

      codeName : '',
      sortSeq : 0,
      useYn : 'Y',
      regDate : '',
    }
  }, 
  mounted() {
    this.fnGetView()
  },
  methods: {
    fnGetView() {

      if (this.groupCode !== undefined && this.codeValue !== undefined) {

        this.$axios.get(this.$serverUrl + "/codedetails/" + this.groupCode + "/" + this.codeValue, {
          params : this.requestBody,
        }).then((res) => {
          this.groupCode = res.data.group_code
          this.codeValue = res.data.code_value
          this.codeName = res.data.code_name
          this.sortSeq = res.data.sort_seq
          this.useYn = res.data.use_yn
          this.regDate = res.data.reg_date
        })
        .catch((err) => {
          if (err.message.indexOf('Network Error') > -1) {
            alert('네트워크가 원활하지 않습니다.\n잠시 후 다시 시도해주세요.')
          }
        })
      }
    },

    fnList() {

      delete this.requestBody.codeValue
      this.$router.push({
          path: './list',
          query: this.requestBody
        }
      )
    },

    fnView(groupCode, codeValue) {
      this.requestBody.groupCode = groupCode
      this.requestBody.codeValue = codeValue
      this.$router.push({
          path: './detail',
          query: this.requestBody
        }
      )
    },

    async fnSave() {

      if(this.groupCode === '' || this.groupCode === undefined) {
        alert("그룹코드를 입력해주세요.")
        return;
      }

      if(this.codeValue === '' || this.codeValue === undefined) {
        alert("상세코드값을 입력해주세요.")
        return;
      }

      if(this.codeName === '' || this.codeName === undefined) {
        alert("상세코드명을 입력해주세요.")
        return;
      }

      if(this.sortSeq === '' || this.sortSeq === undefined) {
        alert("정렬순번을 입력해주세요.")
        return;
      }

      if(this.useYn === '' || this.useYn === undefined) {
        alert("사용여부를 입력해주세요.")
        return;
      }

      let dupCheck = false;

      let apiUrl = this.$serverUrl + '/codedetails'
      this.form = {
        "group_code": this.groupCode.toUpperCase(),
        "code_value": this.codeValue.toUpperCase(),
        "code_name": this.codeName,
        "sort_seq": this.sortSeq,
        "use_yn": this.useYn,
      }

      if (this.regDate === undefined || this.regDate === '') {

        await this.$axios.get(apiUrl + "/check/" + this.form.group_code + "/" + this.form.code_value)
          .then((res) => {
            dupCheck = res.data
          })
          .catch((err) => {
            if (err.message.indexOf('Network Error') > -1) {
              alert('네트워크가 원활하지 않습니다.\n잠시 후 다시 시도해주세요.')
            }
          })
      }
      
      if(dupCheck) {
        alert("이미 존재하는 상세코드 입니다.\n다른 상세코드를 입력하세요.")
        return
      }
      
      if(!confirm('저장하시겠습니까?')) return

      if (this.regDate === undefined || this.regDate === '') {
        //INSERT

        this.$axios.post(apiUrl, this.form)
          .then((res) => {
            alert('정상적으로 저장되었습니다.')
            this.fnView(res.data.group_code, res.data.code_value);
          })
          .catch((err) => {
            if (err.message.indexOf('Network Error') > -1) {
              alert('네트워크가 원활하지 않습니다.\n잠시 후 다시 시도해주세요.')
            }
          })

      } else {
        //UPDATE
        this.$axios.patch(apiUrl + "/" + this.groupCode.toUpperCase() + "/" + this.codeValue.toUpperCase(), this.form)
          .then((res) => {
            alert('정상적으로 저장되었습니다.')
            this.fnView(res.data.group_code, res.data.code_value);
          })
          .catch((err) => {
            if (err.message.indexOf('Network Error') > -1) {
              alert('네트워크가 원활하지 않습니다.\n잠시 후 다시 시도해주세요.')
            }
          })
      }
    },
  }
}


</script>

기존 그룹코드와 유사하게 등록과 수정을 동시에 처리할 수 있도록 하였다.

 

3. 공통코드 상세의 상세

  CodeDetailDetail.vue 파일

<template>
  <div class="board-detail">
    <div class="common-buttons">
      <button type="button" class="w3-button w3-round w3-blue-gray" v-on:click="fnUpdate">수정</button>&nbsp;
      <button type="button" class="w3-button w3-round w3-red" v-on:click="fnDelete">삭제</button>&nbsp;
      <button type="button" class="w3-button w3-round w3-gray" v-on:click="fnList">목록</button>
    </div>
    <div class="board-content">
      <h3>그룹코드 : {{ groupCode }}</h3>
      <div>
        상세코드값 : <strong class="w3-large">{{ codeValue }}</strong>
      </div>
      <div>
        상세코드명 : <strong class="w3-large">{{ codeName }}</strong>
      </div>
      <div>
        정렬순서 : <strong class="w3-large">{{ sortSeq }}</strong>
      </div>
      <div>
        사용여부 : {{ useYn }}
      </div>
    </div>
    <div class="board-content">
      등록일시 : <span>{{ regDate }}</span>
    </div>
    <div class="common-buttons">
      <button type="button" class="w3-button w3-round w3-blue-gray" v-on:click="fnUpdate">수정</button>&nbsp;
      <button type="button" class="w3-button w3-round w3-red" v-on:click="fnDelete">삭제</button>&nbsp;
      <button type="button" class="w3-button w3-round w3-gray" v-on:click="fnList">목록</button>
    </div>
  </div>
</template>


<script>
export default {

  data() {
    return {
      requestBody : this.$route.query,
      groupCode : this.$route.query.groupCode,
      codeValue : this.$route.query.codeValue,

      codeName : '',
      sortSeq : 0,
      useYn : 'Y',
      regDate : '',
    }
  }, 
  mounted() {
    this.fnGetView()
  },
  computed() {

  },

  methods: {
    fnGetView() {
      this.$axios.get(this.$serverUrl + "/codedetails/" + this.groupCode + "/" + this.codeValue, {
        params : this.requestBody,
      }).then((res) => {
          this.groupCode = res.data.group_code
          this.codeValue = res.data.code_value
          this.codeName = res.data.code_name
          this.sortSeq = res.data.sort_seq
          this.useYn = res.data.use_yn
          this.regDate = res.data.reg_date
      })
      .catch((err) => {
        if (err.message.indexOf('Network Error') > -1) {
          alert('네트워크가 원활하지 않습니다.\n잠시 후 다시 시도해주세요.')
        }
      })
    },

    fnList() {

      delete this.requestBody.codeValue
      this.$router.push({
          path: './list',
          query: this.requestBody
        }
      )
    },

    fnUpdate() {

      this.$router.push({
          path: './write',
          query: this.requestBody
        }
      )
    },

    fnDelete() {
      if(!confirm('삭제하시겠습니까?')) return

      this.$axios.delete(this.$serverUrl + "/codedetails/" + this.groupCode + "/" + this.codeValue, {})
        .then(() => {
          alert('정상적으로 삭제되었습니다.')
          
          this.fnList();
        })
        .catch((err) => {
            console.log(err)
        })
    },
  }
}
</script>

이전 장에서 설명했지만 여기서 삭제는 실제 데이터 삭제가 아니고 사용여부만 Y로 변경된다.


이렇게 페이지를 생성한 뒤에 라우터에 추가를 하고 메뉴도 추가하자.

 

4. code.js 라우터

   src/router/code.js 파일에 아래와 같이 상세코드에 대해서 추가 작성한다. 

   beforeEnter도 바로 적용하였다. 

import CodeGroupList from '@/views/code/CodeGroupList.vue'
import CodeGroupDetail from '@/views/code/CodeGroupDetail.vue'
import CodeGroupWrite  from '@/views/code/CodeGroupWrite.vue'

import CodeDetailList from '@/views/code/CodeDetailList.vue'
import CodeDetailDetail from '@/views/code/CodeDetailDetail.vue'
import CodeDetailWrite  from '@/views/code/CodeDetailWrite.vue'

import axios from "@/util/axios"

export const CodeRouters = [
  {
    path: '/codegroup/list',
    name: 'CodeGroupList',
    component: CodeGroupList,
    beforeEnter: axios.requireAuth()
  },
  {
    path: '/codegroup/detail',
    name: 'CodeGroupDetail',
    component: CodeGroupDetail,
    beforeEnter: axios.requireAuth()
  },
  {
    path: '/codegroup/write',
    name: 'CodeGroupWrite',
    component: CodeGroupWrite,
    beforeEnter: axios.requireAuth()
  },
  {
    path: '/codedetail/list',
    name: 'CodeDetailList',
    component: CodeDetailList,
    beforeEnter: axios.requireAuth()
  },
  {
    path: '/codedetail/detail',
    name: 'CodeDetailDetail',
    component: CodeDetailDetail,
    beforeEnter: axios.requireAuth()
  },
  {
    path: '/codedetail/write',
    name: 'CodeDetailWrite',
    component: CodeDetailWrite,
    beforeEnter: axios.requireAuth()
  },
]

 

상세코드에서는 routers.js 에 추가나 메뉴바에 추가는 필요없다.

 

 

5. 그룹코드 리스트 수정 

   그룹코드 리스트 화면에서 상세코드로 넘어갈 수 있도록 버튼에 함수를 추가한다.

   파일은 기존에 개발된 /views/code/CodeGroupList.vue 파일이다.

... 중략
    <tr v-else v-for="(row, no) in list" :key="no">
      <td>{{ (this.page - 1)*size + (no+1) }}</td>
      <td>{{ row.group_code }}</td>
      <td><a v-on:click="fnView(`${row.group_code}`)">{{ row.group_name }}</a></td>
      <td>{{ row.use_yn }}</td>
      <td>{{ row.reg_date }}</td>
      <td><input type="button" name="codeDetail" value="상세코드" v-on:click="fnDetailView(`${row.group_code}`)"></td>
    </tr>
... 중략

... 중략
    ,
    fnDetailView(groupCode) {
      this.requestBody.groupCode = groupCode
      this.$router.push({
        path : '/codedetail/list',
        query: this.requestBody
      })
    },
... 중략

 

 

작성이 완료되었다면 로그인하고 코드그룹 메뉴로 접근한 뒤에 '상세코드' 버튼을 이용해서 접근한 뒤에 

여러가지 테스트를 해보자.

 

테스트를 위해서 임시로 데이터를 생성 시킨 뒤에 화면 접속을 해보면 좋을 거 같다.

 

 

 

이번 장까지는 일단 그룹코드와 상세코드를 각각 단독으로 처리하였다.

다음 장에서는 상세와 그룹코드와의 연계성을 확인할 수 있는 화면에 대한 코딩을 진행해보겠다.

 

추가 팁하나
지금까지 콘솔에 찍히는 쿼리가 한 줄로 표현되고 값이 어떤게 들어가는지 확인하기가 어렵다.
그래서 쿼리를 포맷하고 입력값이 뭔지를 알 수 있도록 환경을 조정하겠다.

application.yml 파일에 아래와 같이 추가시킨 다음에 로그를 한번 보면 포맷팅 된 쿼리를 볼 수 있을 것이다.

logging:
       level:
          org.hibernate.orm.jdbc.bind: trace

 

 

반응형

프로그램/Vue.js Related Articles

MORE

Comments