322 lines
9.7 KiB
Vue
322 lines
9.7 KiB
Vue
<template>
|
|
<div>
|
|
<!-- 참조: https://codesandbox.io/s/3v0m1?file=/src/components/board/BoardList.vue -->
|
|
<b-container fluid>
|
|
<b-row>
|
|
<b-col class="border">
|
|
<b-input-group>
|
|
<label class="input-group-text">
|
|
<b-form-checkbox @change="rowSelectAllToggle"
|
|
>All</b-form-checkbox
|
|
>
|
|
</label>
|
|
<b-form-select
|
|
v-model="selectMode"
|
|
:options="selectModes"
|
|
></b-form-select>
|
|
</b-input-group>
|
|
</b-col>
|
|
<b-col cols="6" class="border">
|
|
<b-input-group>
|
|
<label class="input-group-text">
|
|
<b-form-checkbox-group
|
|
class="d-flex flex-nowrap"
|
|
v-model="searchFields"
|
|
:options="searchOptions"
|
|
></b-form-checkbox-group>
|
|
</label>
|
|
<b-form-input
|
|
v-model="search"
|
|
type="text"
|
|
placeholder="검색어"
|
|
></b-form-input>
|
|
<b-button @click="searchClick">검색</b-button>
|
|
</b-input-group>
|
|
</b-col>
|
|
<b-col class="border">
|
|
<b-input-group class="justify-content-end">
|
|
<label class="input-group-text">줄수</label>
|
|
<b-form-select
|
|
v-model="perPage"
|
|
:options="perPageOptions"
|
|
@change="perPageClick"
|
|
></b-form-select>
|
|
</b-input-group>
|
|
</b-col>
|
|
</b-row>
|
|
<b-row class="overflow-auto">
|
|
<b-table
|
|
id="todoTable"
|
|
ref="todoTable"
|
|
:items="rows"
|
|
:fields="fields"
|
|
:per-page="perPage"
|
|
:current-page="currentPage"
|
|
:sort-by.sync="sortBy"
|
|
:sort-desc.sync="sortDesc"
|
|
:sort-direction="sortDirection"
|
|
label-sort-asc=""
|
|
label-sort-desc=""
|
|
label-sort-clear=""
|
|
:select-mode="selectMode"
|
|
selectable
|
|
@row-selected="rowSelectedToggle"
|
|
:busy="isBusy"
|
|
:sticky-header="commonTableAttributes.stickyHeader"
|
|
:no-border-collapse="commonTableAttributes.noBorderCollapse"
|
|
:striped="commonTableAttributes.striped"
|
|
:hover="commonTableAttributes.hover"
|
|
:bordered="commonTableAttributes.bordered"
|
|
:dark="commonTableAttributes.dark"
|
|
:head-variant="commonTableAttributes.headVariant"
|
|
>
|
|
<!-- 비/선택 Row를 토글용 -->
|
|
<template #cell(rowSelect)="{ rowSelected }">
|
|
<template v-if="rowSelected">
|
|
<span aria-hidden="true">✓</span>
|
|
</template>
|
|
<template v-else>
|
|
<span aria-hidden="true"> </span>
|
|
</template>
|
|
</template>
|
|
<!-- Row의 Index를 이용한 번호 출력 -->
|
|
<template #cell(id)="row">
|
|
<b-link ref="edit/{{row.item.id}}">
|
|
{{ total - (currentPage * perPage + row.index) + perPage }}
|
|
</b-link>
|
|
</template>
|
|
<!-- 제목부분 출력용 -->
|
|
<template #cell(title)="row">
|
|
{{ row.item.title }}
|
|
</template>
|
|
<!-- 상세 내용 출력용 -->
|
|
<template #cell(content)="row">
|
|
<b-button size="sm" @click="row.toggleDetails" class="mr-2">
|
|
{{ row.detailsShowing ? '숨기기' : '보기' }}
|
|
</b-button>
|
|
</template>
|
|
<template #row-details="row">
|
|
<b-card>
|
|
<b-row>
|
|
<b-col v-html="row.item.content"></b-col>
|
|
</b-row>
|
|
<b-button size="sm" @click="row.toggleDetails">숨기기</b-button>
|
|
</b-card>
|
|
</template>
|
|
<!-- 데이터 로딩중 출력용 -->
|
|
<template #table-busy>
|
|
<div class="text-center text-danger my-2">
|
|
<b-spinner class="align-middle"></b-spinner>
|
|
<strong>Loading...</strong>
|
|
</div>
|
|
</template>
|
|
</b-table>
|
|
</b-row>
|
|
<b-row>
|
|
<b-col>
|
|
<p>{{ selectedRows }}</p>
|
|
</b-col>
|
|
<b-col>
|
|
<b-pagination
|
|
v-model="currentPage"
|
|
:total-rows="total"
|
|
:per-page="perPage"
|
|
@page-click="pageClick"
|
|
last-number
|
|
aria-controls="todoTable"
|
|
class="justify-content-center"
|
|
>
|
|
<template #page="{ page, active }">
|
|
<b v-if="active">{{ page }}</b>
|
|
<i v-else>{{ page }}</i>
|
|
</template>
|
|
</b-pagination>
|
|
</b-col>
|
|
<b-col>
|
|
<b-input-group class="justify-content-end">
|
|
<b-button @click="busyToggle">Toggle Busy State</b-button>
|
|
</b-input-group>
|
|
</b-col>
|
|
</b-row>
|
|
</b-container>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
// 참조 : https://vuejsexamples.com/vuejs-tables-and-select-all-checkbox/
|
|
import axios from 'axios'
|
|
export default {
|
|
components: {},
|
|
data: function () {
|
|
return {
|
|
rows: [],
|
|
fields: [
|
|
{ key: 'rowSelect', label: '✓', thStyle: { width: '55px' } },
|
|
{
|
|
key: 'id',
|
|
label: '번호',
|
|
thStyle: { width: '65px' },
|
|
variant: 'primary',
|
|
sortable: true
|
|
},
|
|
{
|
|
key: 'title',
|
|
label: '제목',
|
|
sortable: true
|
|
},
|
|
{
|
|
key: 'content',
|
|
label: '내용',
|
|
sortable: true
|
|
},
|
|
{
|
|
key: 'is_done',
|
|
label: '사용여부',
|
|
thStyle: { width: '105px' },
|
|
formatter: (value) => {
|
|
return value ? 'Yes' : 'No'
|
|
},
|
|
sortable: true,
|
|
sortByFormatted: true //fomatter결과에따른 Sort가 필요시 true
|
|
},
|
|
// { key: 'updateAt', label: '수정일' },
|
|
{
|
|
key: 'createdAt',
|
|
label: '등록일',
|
|
thStyle: { width: '105px' },
|
|
formatter: (value) => {
|
|
return value.replace(
|
|
/([0-9]{4})-([0-9]{2})-([0-9]{2}).*/gi,
|
|
'$1-$2-$3'
|
|
)
|
|
},
|
|
sortable: true,
|
|
sortByFormatted: true //fomatter결과에따른 Sort가 필요시 true
|
|
}
|
|
],
|
|
total: 0,
|
|
currentPage: 1, // 현재 페이지
|
|
perPage: 5, // 페이지당 보여줄 갯수
|
|
perPageOptions: [
|
|
{ text: '5줄', value: 5 },
|
|
{ text: '10줄', value: 10 },
|
|
{ text: '30줄', value: 30 },
|
|
{ text: '60줄', value: 60 },
|
|
{ text: '100줄', value: 100 }
|
|
],
|
|
// 속성옵션
|
|
commonTableAttributes: {
|
|
stickyHeader: '50%',
|
|
//noBorderCollapse: false,
|
|
striped: true,
|
|
hover: true,
|
|
bordered: true,
|
|
dark: false,
|
|
headVariant: 'light'
|
|
},
|
|
isBusy: false,
|
|
sortBy: 'id',
|
|
sortDesc: true,
|
|
sortDirection: 'desc',
|
|
search: null, //DB검색
|
|
searchFields: ['title', 'content'],
|
|
searchOptions: [
|
|
{ text: '제목', value: 'title' },
|
|
{ text: '내용', value: 'content' },
|
|
{ text: '수정일', value: 'updateAt' },
|
|
{ text: '등록일', value: 'createAt' }
|
|
],
|
|
selectModes: ['multi', 'single', 'range'],
|
|
selectMode: 'multi',
|
|
selectedAllToggle: false,
|
|
selectedRows: []
|
|
}
|
|
},
|
|
setup: function () {},
|
|
created: function () {},
|
|
mounted: function () {
|
|
this.getDatas()
|
|
},
|
|
unmounted() {},
|
|
methods: {
|
|
async getDatas() {
|
|
this.isBusy = true
|
|
const results = await this.callAPI('/todo', {
|
|
params: {
|
|
sortBy: this.sortBy,
|
|
sortDirection: this.sortDirection,
|
|
searchFields: this.searchFields,
|
|
search: this.search,
|
|
page: this.currentPage,
|
|
perPage: this.perPage
|
|
}
|
|
})
|
|
//console.log(JSON.stringify(results))
|
|
console.log(results)
|
|
this.total = results.total
|
|
this.perPage = results.perPage
|
|
this.page = results.page
|
|
this.rows = results.rows
|
|
this.isBusy = false
|
|
},
|
|
searchClick() {
|
|
this.currentPage = 1
|
|
this.getDatas()
|
|
},
|
|
pageClick(bvEvent, page) {
|
|
console.log(bvEvent)
|
|
this.currentPage = page
|
|
this.getDatas()
|
|
bvEvent.preventDefault()
|
|
},
|
|
perPageClick(perPage) {
|
|
this.currentPage = 1
|
|
this.perPage = perPage
|
|
console.log(this.perPage)
|
|
this.getDatas()
|
|
},
|
|
busyToggle() {
|
|
this.isBusy = !this.isBusy
|
|
},
|
|
rowSelectedToggle(selectedRow) {
|
|
this.selectedRows = selectedRow
|
|
},
|
|
rowSelectAllToggle() {
|
|
if (this.selectedAllToggle) {
|
|
this.$refs.todoTable.clearSelected()
|
|
this.selectedAllToggle = false
|
|
} else {
|
|
this.$refs.todoTable.selectAllRows()
|
|
this.selectedAllToggle = true
|
|
}
|
|
},
|
|
// rowSelectSet(id) {
|
|
// // Rows are indexed from 0, so the third row is index 2
|
|
// this.$refs.todoTable.selectRow(id)
|
|
// },
|
|
// rowSelectUnSet(id) {
|
|
// // Rows are indexed from 0, so the third row is index 2
|
|
// this.$refs.todoTable.unselectRow(id)
|
|
// }
|
|
async callAPI(url, params) {
|
|
console.log('CallAPI..', [url, params])
|
|
axios.defaults.baseURL = process.env.VUE_APP_BACKEND_HOST
|
|
// axios.defaults.headers.post['Content-Type'] =
|
|
// process.env.VUE_APP_BACKEND_HEADERS_Content_Type
|
|
// axios.defaults.headers.post['Access-Control-Allow-Origin'] =
|
|
// process.env.VUE_APP_BACKEND_HEADERS_Access_Control_Allow_Origin
|
|
return await axios
|
|
.get(url, params)
|
|
.then((response) => {
|
|
return response.status === 200 ? response.data : []
|
|
})
|
|
.catch((err) => {
|
|
console.log(err)
|
|
return []
|
|
})
|
|
}
|
|
},
|
|
computed: {}
|
|
}
|
|
</script>
|
|
<style scoped></style>
|