pagination.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <template>
  2. <div class="pagination-wrapper">
  3. <!-- 첫 페이지 이동-->
  4. <v-btn class="pagination-btn prev2" :disabled="pageObj.page == 1 || pageObj.pageMaxNumSize >= totalPages" @click="$emit('chg_page', 1)"></v-btn>
  5. <!-- 왼쪽 이동 -->
  6. <v-btn class="pagination-btn prev1" :disabled="pageObj.page == 1" @click="$emit('chg_page', pageObj.page - 1)"></v-btn>
  7. <!-- 첫페이지 -->
  8. <v-btn class="pagination-btn number" :class="{'on':pageObj.page==1}" @click="$emit('chg_page', 1)" v-if="totalPages>0">1</v-btn>
  9. <!-- 첫 번째 ellipsis -->
  10. <span class="pagination-btn more" v-if="showStartEllipsis"></span>
  11. <!-- 중간 페이지 -->
  12. <v-btn
  13. v-for="page in visiblePages"
  14. :key="page"
  15. @click="$emit('chg_page', page)"
  16. class="pagination-btn number"
  17. :class="{'on':page === pageObj.page}"
  18. >
  19. {{ page }}
  20. </v-btn>
  21. <!-- 두 번째 ellipsis -->
  22. <span class="pagination-btn more" v-if="showEndEllipsis"></span>
  23. <!-- 마지막 페이지 -->
  24. <v-btn class="pagination-btn number" :class="{'on':pageObj.page === totalPages}" @click="$emit('chg_page', totalPages)" v-if="totalPages!==0 && totalPages !== 1">{{ totalPages }}</v-btn>
  25. <!-- 오른쪽 이동 -->
  26. <v-btn class="pagination-btn next1" :disabled="pageObj.page == totalPages || pageObj.totalCnt == 0" @click="$emit('chg_page', pageObj.page + 1)"></v-btn>
  27. <!-- 마지막 페이지 이동-->
  28. <v-btn class="pagination-btn next2" :disabled="pageObj.page == totalPages || pageObj.totalCnt == 0 || pageObj.pageMaxNumSize >= totalPages" @click="$emit('chg_page', totalPages)"></v-btn>
  29. <div class="page-go">
  30. <v-text-field
  31. v-model="pageGo"
  32. class="custom-input mini"
  33. style="width:calc(1vw * (70 / 19.2))"
  34. ></v-text-field>
  35. <button @click="fnPageGo">Go</button>
  36. </div>
  37. </div>
  38. </template>
  39. <script setup>
  40. import { computed, ref } from 'vue';
  41. const {$toast, $log, $eventBus } = useNuxtApp()
  42. let pageId = 'pagination'
  43. // props
  44. const props = defineProps({
  45. pageObj: Object,
  46. })
  47. // 발신 이벤트 선언
  48. const emit = defineEmits(['chg_page'])
  49. // data
  50. const pageGo = ref(1) // 입력 페이지
  51. const pageGoClone = ref(1) // 복구 페이지
  52. // 페이지 복구
  53. $eventBus.off('SET_INIT_PAGE')
  54. $eventBus.on('SET_INIT_PAGE', () => {
  55. if(!useUtil.isNull(pageGoClone.value)) {
  56. pageGo.value = pageGoClone.value
  57. }
  58. })
  59. $eventBus.off('SET_PAGE')
  60. $eventBus.on('SET_PAGE', (param) => {
  61. pageGo.value = param
  62. })
  63. // 전체 페이지수(마지막 페이지)
  64. const totalPages = computed(() => {
  65. return Math.ceil(props.pageObj.totalCnt / props.pageObj.pageSize)
  66. })
  67. // 첫, 마지막 페이지 제외한 노출 페이지 리스트
  68. const visiblePages = computed(() => {
  69. const pages = []
  70. // 현재 페이지 기준 좌우에 표현할 수
  71. const halfRange = Math.floor((props.pageObj.pageMaxNumSize - 4) / 2) // ...페이지 2개, 첫번째 마지막페이지 2개로 인해 -4를 한다
  72. let start = props.pageObj.page - halfRange
  73. let end = props.pageObj.page + halfRange
  74. if (start < 2) {
  75. start = 2
  76. end = start + (props.pageObj.pageMaxNumSize - 4)
  77. }
  78. if (end >= totalPages.value) {
  79. end = totalPages.value - 1
  80. start = end - (props.pageObj.pageMaxNumSize - 4)
  81. if (start < 2) {
  82. start = 2
  83. }
  84. }
  85. for (let i = start; i <= end; i++) {
  86. pages.push(i)
  87. }
  88. return pages
  89. })
  90. // 첫 번째 ellipsis
  91. const showStartEllipsis = computed(() => {
  92. return visiblePages.value.length && visiblePages.value[0] > 2
  93. })
  94. // 두 번째 ellipsis
  95. const showEndEllipsis = computed(() => {
  96. return visiblePages.value.length && visiblePages.value[visiblePages.value.length - 1] < totalPages.value - 1
  97. })
  98. /**
  99. * 페이지 입력 이동
  100. */
  101. function fnPageGo(){
  102. let page = Number(pageGo.value)
  103. if(page > totalPages.value) {
  104. fnErrorPageAlert()
  105. }else if(page < 1){
  106. fnErrorPageAlert()
  107. }else{
  108. emit('chg_page', page)
  109. pageGoClone.value = _cloneDeep(page)
  110. }
  111. }
  112. /**
  113. * 입력페이지 에러 comfirm alert
  114. */
  115. function fnErrorPageAlert(){
  116. let param = {
  117. id: pageId,
  118. title:'Notice',
  119. content:'입력하신 페이지가 존재하지 않습니다.',
  120. yes:{
  121. text:'OK',
  122. isProc:true,
  123. event:'SET_INIT_PAGE',
  124. param:{},
  125. }
  126. }
  127. $eventBus.emit('OPEN_CONFIRM_POP_UP', param)
  128. }
  129. </script>
  130. <style lang="scss" scoped>
  131. </style>