301 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			301 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# bio_frontend
 | 
						||
 | 
						||
## NUXT 3 (VUE 3) 환경
 | 
						||
 - data-list 와 dataList는 동일 변수명으로 인식
 | 
						||
 - compnenets 아래의 .vue는 자동 인식(template 내부에서만, 별도 script에서 필요시 선언 필요)
 | 
						||
 | 
						||
 | 
						||
# 구성 요소
 | 
						||
## components 구성
 | 
						||
```
 | 
						||
components
 | 
						||
 |- base      // 기본 요소(button, input, grid, popup)
 | 
						||
 |- layout    // 레이아웃 요소(header, footer, sidebar, wrapper)
 | 
						||
 |- module    // 특정 기능 단위(card, form, list)
 | 
						||
 |- pages     // 특정 페이지 전용
 | 
						||
```
 | 
						||
 | 
						||
## page 구성
 | 
						||
```
 | 
						||
pages         // 단일 화면(비 탭 요소)
 | 
						||
|- popup      // 팝업 요소
 | 
						||
|- [tabId]    // 탭 요소
 | 
						||
    |- admin  // 관리자 페이지
 | 
						||
 | 
						||
```
 | 
						||
 | 
						||
# page(페이지) 생성 요소
 | 
						||
## 공통 페이지 구성
 | 
						||
```
 | 
						||
<template>
 | 
						||
    <ContentsWrapper> <!-- wrapper(title) 추가 -->
 | 
						||
        <template #actions> <!--title 우측 버튼 설정-->
 | 
						||
            <button>추가</button>
 | 
						||
            <button>저장</button>
 | 
						||
        </template>
 | 
						||
        <!--메인 콘텐츠 영역-->
 | 
						||
        <input type="text" >
 | 
						||
        <!--메인 콘텐츠 영역-->
 | 
						||
    </ContentsWrapper>
 | 
						||
</template>
 | 
						||
<script setup lang="ts">
 | 
						||
    // title(wrapper) 설정
 | 
						||
    definePageMeta({
 | 
						||
        title: '리소스 관리'
 | 
						||
    })
 | 
						||
</script>
 | 
						||
```
 | 
						||
 | 
						||
 | 
						||
## Toast(Tui) Grid 사용법
 | 
						||
한글 설명: https://github.com/nhn/tui.grid/blob/master/packages/toast-ui.grid/docs/v4.0-migration-guide-kor.md
 | 
						||
 | 
						||
 | 
						||
### 기본 설정
 | 
						||
```
 | 
						||
<template>
 | 
						||
    <button @click="onAddClick">추가</button>
 | 
						||
    <button @click="onUpdateClick">저장</button>
 | 
						||
 | 
						||
    <!-- toast Grid 필수값 ref, data, columns(header) -->
 | 
						||
    <ToastGrid  
 | 
						||
        ref="grid1Ref"
 | 
						||
        :data="data"
 | 
						||
        :columns="colDefs"
 | 
						||
    />        
 | 
						||
</template>
 | 
						||
  
 | 
						||
<script setup lang="ts">
 | 
						||
// 컬럼 항목 리스트
 | 
						||
// composables폴더 아래에 생성
 | 
						||
// 위 한글 성명 참조하여 생성
 | 
						||
import {colDefs} from '../../composables/grids/resourceGrid'
 | 
						||
 | 
						||
// 데이터 항목
 | 
						||
const data = [{}]
 | 
						||
 | 
						||
// ref 설정
 | 
						||
// api : https://nhn.github.io/tui.grid/latest/Grid
 | 
						||
const grid1Ref = ref();
 | 
						||
 | 
						||
onMounted(async () => {
 | 
						||
  await nextTick() // DOM 및 컴포넌트 렌더링 완료 대기
 | 
						||
  grid1Ref.value?.api()?.setBodyHeight('700') // ref api를 통해서 높이 지정
 | 
						||
})
 | 
						||
 | 
						||
let no = 1;
 | 
						||
 | 
						||
// 항목 추가 버튼
 | 
						||
function onAddClick() {
 | 
						||
  grid1Ref.value?.api()?.appendRow({'no': no}); // ref api를 통해서 항목 추가  
 | 
						||
  ++no;
 | 
						||
}
 | 
						||
 | 
						||
// 저장 버튼
 | 
						||
function onUpdateClick() {
 | 
						||
   //grid1Ref.value?.clearGrid();
 | 
						||
  const chageList = grid1Ref.value?.api()?.getModifiedRows(); // ref api를 통해서 변경점 읽어오기
 | 
						||
  console.log(changeList);  
 | 
						||
}
 | 
						||
</script>
 | 
						||
```  
 | 
						||
 | 
						||
## tree data
 | 
						||
```
 | 
						||
<template>
 | 
						||
  <ToastGrid  
 | 
						||
    ref="grid1Ref"
 | 
						||
    :data="data"
 | 
						||
    :columns="columns"
 | 
						||
    :treeColumnOptions="treeColumnOptions"
 | 
						||
  />  
 | 
						||
</template>
 | 
						||
 | 
						||
<script setup lang="ts">
 | 
						||
// data 설정시 _children: 항목으로 구성
 | 
						||
const data = [
 | 
						||
  {
 | 
						||
    id: 549731,
 | 
						||
    name: 'Beautiful Lies',
 | 
						||
    price: 10000,
 | 
						||
    downloadCount: 1000,
 | 
						||
    listenCount: 5000,
 | 
						||
    _attributes: {
 | 
						||
      expanded: true,
 | 
						||
    },
 | 
						||
    _children: [
 | 
						||
      {
 | 
						||
        id: 491379,
 | 
						||
        name: 'Chaos And The Calm',
 | 
						||
        artist: 'James Bay',
 | 
						||
        grade: '5',
 | 
						||
        price: 12000,
 | 
						||
        downloadCount: 1000,
 | 
						||
        listenCount: 5000
 | 
						||
      },
 | 
						||
      {
 | 
						||
        id: 450720,
 | 
						||
        name: "I'm Not The Only One",
 | 
						||
        artist: 'Sam Smith',
 | 
						||
        release: '2014.09.15',
 | 
						||
        type: 'Single',
 | 
						||
        grade: '4',
 | 
						||
        price: 8000,
 | 
						||
        downloadCount: 1000,
 | 
						||
        listenCount: 5000,
 | 
						||
        _attributes: {
 | 
						||
          expanded: true,
 | 
						||
        },
 | 
						||
        _children: [
 | 
						||
          {
 | 
						||
            id: 587871,
 | 
						||
            name: 'This Is Acting',
 | 
						||
            artist: 'Sia',
 | 
						||
            release: '2016.10.22',
 | 
						||
            type: 'EP',
 | 
						||
            typeCode: '2',
 | 
						||
            genre: 'Pop',
 | 
						||
            _attributes: {
 | 
						||
              expanded: true,
 | 
						||
            },
 | 
						||
            _children: [
 | 
						||
              {
 | 
						||
                id: 490500,
 | 
						||
                name: 'Blue Skies',
 | 
						||
                release: '2015.03.18',
 | 
						||
                artist: 'Lenka',
 | 
						||
                type: 'Single',
 | 
						||
                typeCode: '3',
 | 
						||
              },
 | 
						||
              {
 | 
						||
                id: 317659,
 | 
						||
                name: "I Won't Give Up",
 | 
						||
                artist: 'Jason Mraz',
 | 
						||
                release: '2012.01.03',
 | 
						||
                type: 'Single',
 | 
						||
                typeCode: '3',
 | 
						||
              },
 | 
						||
            ],
 | 
						||
          },
 | 
						||
        ],
 | 
						||
      },
 | 
						||
    ],
 | 
						||
  },
 | 
						||
  {
 | 
						||
    id: 436461,
 | 
						||
    name: 'X',
 | 
						||
    artist: 'Ed Sheeran',
 | 
						||
    release: '2014.06.24',
 | 
						||
    type: 'Deluxe',
 | 
						||
    typeCode: '1',
 | 
						||
  },
 | 
						||
];
 | 
						||
 | 
						||
const columns = [
 | 
						||
  { header: 'Name', name: 'name', width: 300 },
 | 
						||
  { header: 'Artist', name: 'artist' },
 | 
						||
  { header: 'Type', name: 'type' },
 | 
						||
  { header: 'Release', name: 'release' },
 | 
						||
  { header: 'Genre', name: 'genre' },
 | 
						||
];
 | 
						||
 | 
						||
// tree column 설정
 | 
						||
const treeColumnOptions = { name: 'name', useCascadingCheckbox: true };
 | 
						||
 | 
						||
const grid1Ref = ref();
 | 
						||
</script>
 | 
						||
```
 | 
						||
 | 
						||
## 팝업 구성
 | 
						||
 | 
						||
```
 | 
						||
┌─────────────────────────────┐
 | 
						||
│      customPopup.vue        │
 | 
						||
│ ┌─────────────────────────┐ │
 | 
						||
│ │      poupWrapper.vue    │ │
 | 
						||
│ │ ┌─────────────────────┐ │ │
 | 
						||
│ │ │        <slot>       │ │ │
 | 
						||
│ │ └─────────────────────┘ │ │
 | 
						||
│ └─────────────────────────┘ │
 | 
						||
└─────────────────────────────┘
 | 
						||
 | 
						||
 | 
						||
customPopup.vue - 기본 빈 팝업
 | 
						||
poupWrapper.vue - top, middle, bottom으로 구성된 팝업 구조
 | 
						||
 | 
						||
1. 구조에 따라 customPopup, poupWrapper 기반으로 팝업 생성(/pages/popup/*.vue)
 | 
						||
2. 사용할 페이지에서 생성한 팝업 추가
 | 
						||
```
 | 
						||
 | 
						||
 | 
						||
### 팝업 생성
 | 
						||
```
 | 
						||
// examplePopup.vue
 | 
						||
<template>
 | 
						||
  <div>
 | 
						||
    <!--PopupWrapper 구성, 크기 지정, 숨김 여부 지정 -->
 | 
						||
    <PopupWrapper width="1000px" height="600px" v-model:show="show">
 | 
						||
      <template #top>
 | 
						||
        <h2>팝업 제목</h2>
 | 
						||
      </template>
 | 
						||
  
 | 
						||
      <template #middle>
 | 
						||
        <!-- 팝업 본문 -->
 | 
						||
      </template>
 | 
						||
  
 | 
						||
      <template #bottom>
 | 
						||
        <button>추가 버튼</button>
 | 
						||
        <!-- 닫기 버튼은 자동 생성 -->
 | 
						||
      </template>
 | 
						||
    </PopupWrapper>
 | 
						||
  </div>
 | 
						||
</template>
 | 
						||
  
 | 
						||
<script setup lang="ts">
 | 
						||
  // 숨김 여부 지정
 | 
						||
  const show = defineModel('show', {type: Boolean, default:false});
 | 
						||
</script>
 | 
						||
```
 | 
						||
 | 
						||
### 팝업 사용
 | 
						||
```
 | 
						||
<template>
 | 
						||
  <button @click="popupShow = true">팝업 실행</button>
 | 
						||
  <examplePopup v-model:show="popupShow" />
 | 
						||
</template>
 | 
						||
<script setup lang="ts">
 | 
						||
  import addSamplePopup from '../popup/examplePopup.vue';
 | 
						||
  const popupShow = ref(false);
 | 
						||
</script>
 | 
						||
```
 | 
						||
 | 
						||
 | 
						||
## 탭 구성
 | 
						||
```
 | 
						||
// layouts/default.vue
 | 
						||
// stores/tab.ts
 | 
						||
 | 
						||
import { useTabsStore } from "../stores/tab";
 | 
						||
const tabsStore = useTabsStore();
 | 
						||
 | 
						||
// 탭추가 (최대 10개)
 | 
						||
tabsStore.addTab();
 | 
						||
 | 
						||
// 탭 갱신
 | 
						||
tabsStore.updateActiveTab({ label, to, componentName});
 | 
						||
 | 
						||
// 탭 변경
 | 
						||
tabsStore.setActiveTab(key);
 | 
						||
 | 
						||
// 탭 생성
 | 
						||
<div
 | 
						||
  v-for="tab in tabsStore.tabs"
 | 
						||
  :key="tab.key"
 | 
						||
  class="tab-item"
 | 
						||
  :class="{ active: tabsStore.activeTab === tab.key }"
 | 
						||
  @click="tabsStore.setActiveTab(tab.key);"
 | 
						||
>
 | 
						||
  {{ tab.label }}
 | 
						||
  <span v-show="tabsStore.activeTab !== tab.key" class="close-btn" @click.stop="tabsStore.removeTab(tab.key)"> × </span>
 | 
						||
</div>
 | 
						||
``` |