CommonTable.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. <template>
  2. <div class="tablePaganations">
  3. <a-table
  4. class="ant-table-striped"
  5. bordered
  6. size="small"
  7. height="1000px"
  8. :loading="isLoading"
  9. :data-source="dataSource"
  10. :columns="columns"
  11. :row-key="(record) => record.id"
  12. :scroll="scrollValue"
  13. :pagination="havePage ? pagination : false"
  14. :row-selection="
  15. isSelect
  16. ? {
  17. selectedRowKeys: state.selectedRowKeys,
  18. onSelect: selectEvent,
  19. onSelectAll: selectAllEvent,
  20. }
  21. : null
  22. "
  23. :row-class-name="
  24. (_record, index) => (index % 2 === 1 ? 'table-striped' : null)
  25. "
  26. @resize-column="handleResizeColumn"
  27. >
  28. <template
  29. v-for="(item, index) in renderArr"
  30. #[item]="scope"
  31. :key="index"
  32. >
  33. <slot :name="item" :scope="scope" v-bind="scope || {}" />
  34. </template>
  35. </a-table>
  36. </div>
  37. </template>
  38. <script setup>
  39. import {
  40. useSlots,
  41. ref,
  42. reactive,
  43. defineProps,
  44. defineEmits,
  45. watch,
  46. onMounted,
  47. defineExpose,
  48. } from 'vue';
  49. const props = defineProps({
  50. dataSource: {
  51. type: Object,
  52. required: true,
  53. },
  54. columns: {
  55. type: Object,
  56. required: true,
  57. },
  58. isSelect: {
  59. type: Boolean,
  60. },
  61. isLoading: {
  62. type: Boolean,
  63. },
  64. total: {
  65. type: Number,
  66. default: 0,
  67. },
  68. havePage: {
  69. type: Boolean,
  70. default: true,
  71. },
  72. scrollValue: {
  73. type: Object,
  74. default: () => ({ y: 410 }),
  75. },
  76. });
  77. // 选择数据
  78. const state = reactive({
  79. selectedRows: [],
  80. selectedRowKeys: [],
  81. });
  82. // 分页配置
  83. const pagination = reactive({
  84. showQuickJumper: true,
  85. current: 1,
  86. pageSize: 20, // 默认每页显示数量
  87. showSizeChanger: true, // 显示可改变每页数量
  88. pageSizeOptions: ['20', '50', '100', '200', '300', '500'], // 每页数量选项值
  89. showTotal: (total, range) =>
  90. range[0] + '-' + range[1] + '条' + ' 共' + total + '条', // 显示总数
  91. onShowSizeChange: (current, pageSize) => showSizeChange(current, pageSize),
  92. onChange: (current, pageSize) => changePage(current, pageSize), //点击页码事件
  93. total: props.total,
  94. });
  95. const emit = defineEmits(['pageParams', 'selectColumn']);
  96. // 改变每页数量时更新显示
  97. const showSizeChange = (current, pageSize) => {
  98. setTimeout(() => {
  99. pagination.current = 1;
  100. emit('pageParams', pagination.current, pageSize);
  101. });
  102. pagination.pageSize = pageSize;
  103. };
  104. //点击页码事件
  105. const changePage = (current, size) => {
  106. pagination.current = current;
  107. emit('pageParams', pagination.current, size);
  108. };
  109. // 选择每一项操作
  110. const selectEvent = (record, selected, selectedRows) => {
  111. if (selected) {
  112. state.selectedRows.push(record);
  113. state.selectedRowKeys.push(record.id);
  114. } else {
  115. let index = state.selectedRowKeys.indexOf(record.id);
  116. if (index >= 0) {
  117. state.selectedRows.splice(index, 1);
  118. state.selectedRowKeys.splice(index, 1);
  119. }
  120. }
  121. emit('selectColumn', state.selectedRows);
  122. };
  123. // 全选按钮操作
  124. const selectAllEvent = (selected, selectedRows, changeRows) => {
  125. if (selected) {
  126. state.selectedRows = state.selectedRows.concat(changeRows);
  127. state.selectedRows.forEach(item => {
  128. state.selectedRowKeys.push(item.id);
  129. });
  130. } else {
  131. changeRows.forEach(item => {
  132. state.selectedRows.forEach(row => {
  133. if (item.id == row.id) {
  134. state.selectedRows.splice(0, 1);
  135. }
  136. });
  137. let index = state.selectedRowKeys.indexOf(item.id);
  138. if (index >= 0) {
  139. state.selectedRows.splice(index, 1);
  140. state.selectedRowKeys.splice(index, 1);
  141. }
  142. });
  143. }
  144. emit('selectColumn', state.selectedRows);
  145. };
  146. // 伸缩列
  147. const handleResizeColumn = (w, col) => {
  148. col.width = w;
  149. };
  150. // 清空选择
  151. const clear = () => {
  152. state.selectedRowKeys = [];
  153. state.selectedRows = [];
  154. emit('selectColumn', state.selectedRows);
  155. };
  156. // 回到第一页
  157. const backFirstPage = () => {
  158. pagination.current = 1;
  159. emit('pageParams', pagination.current, pagination.pageSize);
  160. };
  161. defineExpose({ clear, backFirstPage });
  162. // 监听total变化
  163. watch(
  164. props,
  165. newData => {
  166. pagination.total = newData.total;
  167. },
  168. { immediate: true, deep: true },
  169. );
  170. // 插槽的实例
  171. const slots = useSlots();
  172. const renderArr = Object.keys(slots);
  173. </script>
  174. <style scoped>
  175. .tablePaganations {
  176. width: 100%;
  177. margin-top: 20px;
  178. margin-bottom: 20px;
  179. }
  180. .ant-table-striped :deep(.table-striped) td {
  181. background-color: #fafafa;
  182. }
  183. </style>