index.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <template>
  2. <div>
  3. <div v-if="isTools" class="text-end mb-3">
  4. <v-btn class="ml-2" color="primary" @click="emit('add')">
  5. <v-icon left>mdi-plus</v-icon>
  6. 新增
  7. </v-btn>
  8. <slot name="addToTools"></slot>
  9. </div>
  10. <v-data-table
  11. ref="table"
  12. :class="`elevation-${elevation} tableColor ${noRadius ? 'noRadius' : ''}`"
  13. :headers="headers"
  14. :items="items"
  15. :item-key="itemKey"
  16. :show-select="showSelect"
  17. :loading="loading"
  18. :select-strategy="selectStrategy"
  19. color="primary"
  20. hover
  21. hide-default-footer
  22. loading-text="Loading... Please wait"
  23. fixed-header
  24. :disable-sort="disableSort"
  25. :items-per-page="itemsPerPage"
  26. :no-data-text="noDataText"
  27. :hide-default-header="hideDefaultHeader"
  28. @update:modelValue="handleSelect"
  29. >
  30. <template v-for="name in itemSlot" v-slot:[`item.${name}`]="slotProps">
  31. <slot :name="name" v-bind="slotProps"></slot>
  32. </template>
  33. <template v-for="name in headerSlot" v-slot:[`${name}`]="slotProps">
  34. <slot :name="name" v-bind="slotProps"></slot>
  35. </template>
  36. <template v-if="!Object.keys(slot).includes('actions')" v-slot:[`item.actions`]="{ item }">
  37. <td>
  38. <v-btn variant="text" color="primary" @click="edit(item)">编辑</v-btn>
  39. <v-btn variant="text" color="error" @click="del(item)">删除</v-btn>
  40. </td>
  41. </template>
  42. <template #bottom>
  43. <div v-if="showPage && total > 0">
  44. <v-divider></v-divider>
  45. <CtPagination :total="total" :page="pageInfo.pageNo" :limit="pageInfo.pageSize" @handleChange="handleChangePage"></CtPagination>
  46. </div>
  47. </template>
  48. </v-data-table>
  49. </div>
  50. </template>
  51. <script setup>
  52. defineOptions({ name: 'CtTable'})
  53. import { ref, computed, useSlots } from 'vue'
  54. const emit = defineEmits(['pageHandleChange', 'del', 'edit', 'add', 'selected'])
  55. defineProps({
  56. elevation: {
  57. type: [Number, String],
  58. default: 0
  59. },
  60. itemKey: {
  61. type: String,
  62. default: 'id'
  63. },
  64. disableSort: {
  65. type: Boolean,
  66. default: true
  67. },
  68. // 展示列表所有数据
  69. itemsPerPage: {
  70. type: Number,
  71. default: -1
  72. },
  73. hideDefaultHeader: {
  74. type: Boolean,
  75. default: false
  76. },
  77. showPage: {
  78. type: Boolean,
  79. default: true
  80. },
  81. loading: {
  82. type: Boolean,
  83. default: true
  84. },
  85. headers: {
  86. type: Array,
  87. default: () => []
  88. },
  89. items: {
  90. type: Array,
  91. default: () => []
  92. },
  93. total: {
  94. type: [String, Number],
  95. default: 0
  96. },
  97. pageInfo: {
  98. type: Object,
  99. default: () => ({
  100. size: 10
  101. })
  102. },
  103. isTools: {
  104. type: Boolean,
  105. default: true
  106. },
  107. height: {
  108. type: [String, Number],
  109. default: ''
  110. },
  111. noRadius: {
  112. type: Boolean,
  113. default: false
  114. },
  115. noDataText: {
  116. type: String,
  117. default: '暂无数据'
  118. },
  119. showSelect: {
  120. type: Boolean,
  121. default: false
  122. },
  123. selectStrategy: {
  124. type: String,
  125. default: 'single'
  126. }
  127. })
  128. const table = ref()
  129. const slot = useSlots()
  130. const itemSlot = computed(() => {
  131. return Object.keys(slot).filter(key => {
  132. const data = key.split('.')
  133. return data.length === 1
  134. })
  135. })
  136. const headerSlot = computed(() => {
  137. return Object.keys(slot).filter(key => {
  138. const data = key.split('.')
  139. return data.length === 2 && data[0] === 'header'
  140. })
  141. })
  142. const edit = (item) => {
  143. emit('edit', item)
  144. }
  145. const del = (item) => {
  146. emit('del', item)
  147. }
  148. const handleChangePage = (e) => {
  149. emit('pageHandleChange', e)
  150. }
  151. const handleSelect = (e) => {
  152. emit('selected', e)
  153. }
  154. </script>
  155. <style scoped lang="scss">
  156. :deep(.v-table > .v-table__wrapper > table > thead) {
  157. background-color: #f7f8fa !important;
  158. }
  159. :deep(.v-selection-control__input) {
  160. color: var(--v-primary-base) !important;
  161. }
  162. </style>