CommonTable.vue 4.6 KB

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