CommonTable.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <template>
  2. <div class="tablePaganations">
  3. <!-- <a-config-provider :locale="locale"> -->
  4. <a-table id="commonTable" class="ant-table-striped" bordered size="small" height="1000px" :loading="isLoading"
  5. :data-source="dataSource" :columns="columns" :row-key="(record) => record.id" :scroll="{ y: yScroll }"
  6. :pagination="havePage ? pagination : false" :row-class-name="(_record, index) => (index % 2 === 1 ? 'table-striped' : null)
  7. " :row-selection="isSelect
  8. ? {
  9. selectedRowKeys: state.selectedRowKeys,
  10. onSelect: selectEvent,
  11. onSelectAll: selectAllEvent,
  12. }
  13. : null
  14. " @change="tableChange" @resize-column="handleResizeColumn">
  15. <template v-for="(item, index) in renderArr" #[item]="scope" :key="index">
  16. <slot :name="item" :scope="scope" v-bind="scope || {}" />
  17. </template>
  18. </a-table>
  19. <!-- </a-config-provider> -->
  20. </div>
  21. </template>
  22. <script setup>
  23. import {
  24. useSlots,
  25. ref,
  26. reactive,
  27. defineProps,
  28. defineEmits,
  29. defineExpose,
  30. watch,
  31. onMounted,
  32. } from 'vue';
  33. import { getTableScroll } from './tableScroll.js';
  34. // import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN';
  35. // const locale = ref(zhCN);
  36. const props = defineProps({
  37. // 表格数据
  38. dataSource: {
  39. type: Object,
  40. required: true,
  41. },
  42. // 表头数据
  43. columns: {
  44. type: Object,
  45. required: true,
  46. },
  47. // 是否可选择
  48. isSelect: {
  49. type: Boolean,
  50. },
  51. // 表格loading
  52. isLoading: {
  53. type: Boolean,
  54. },
  55. // 数据总数
  56. total: {
  57. type: Number,
  58. default: 0,
  59. },
  60. // 是否分页
  61. havePage: {
  62. type: Boolean,
  63. default: true,
  64. },
  65. // 分页在右上角
  66. topRight: {
  67. type: Boolean,
  68. default: false,
  69. },
  70. // 表格距底部高度
  71. extraHeight: {
  72. type: Number,
  73. default: undefined,
  74. },
  75. // 选择的key值
  76. selectedKeys: {
  77. type: Array,
  78. default: () => [],
  79. },
  80. });
  81. const emit = defineEmits(['getPager', 'getSorter', 'getSelected']);
  82. // 分页配置
  83. const pagination = reactive({
  84. showQuickJumper: true,
  85. current: 1,
  86. pageSize: 20, // 默认每页显示数量
  87. showSizeChanger: true, // 显示可改变每页数量
  88. pageSizeOptions: ['10', '20', '50', '100', '200', '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. position: props.topRight ? ['topRight'] : ['bottomRight'],
  95. });
  96. const isPageSizeChange = ref(false);
  97. const yScroll = ref(400); //默认滚动高度
  98. const extraHeight = ref(undefined); //表格距离底部值
  99. // 最后一次排序信息
  100. const lastSorter = reactive({ field: '', order: '' });
  101. // 选择的数据
  102. const state = reactive({
  103. selectedRows: [],
  104. selectedRowKeys: [],
  105. });
  106. onMounted(() => {
  107. if (!props.havePage) {
  108. extraHeight.value = 30;
  109. } else {
  110. extraHeight.value = props.extraHeight;
  111. }
  112. if (props.extraHeight) {
  113. extraHeight.value = props.extraHeight;
  114. }
  115. onResizeTable();
  116. window.onresize = () => {
  117. onResizeTable();
  118. };
  119. });
  120. // 表格位置
  121. const onResizeTable = () => {
  122. yScroll.value = getTableScroll({
  123. extraHeight: extraHeight.value,
  124. id: 'commonTable',
  125. });
  126. };
  127. //点击页码事件
  128. const changePage = (current, size) => {
  129. // pagination.current = current;
  130. // emit('getPager', pagination.current, size);
  131. if (isPageSizeChange.value) {
  132. pagination.current = 1;
  133. isPageSizeChange.value = false;
  134. emit('getPager', 1, size);
  135. } else {
  136. pagination.current = current;
  137. emit('getPager', current, size);
  138. }
  139. pagination.pageSize = size;
  140. };
  141. // 改变每页数量时更新显示,每页条数改变(会自动触发点击页码事件)
  142. const showSizeChange = (current, pageSize) => {
  143. // setTimeout(() => {
  144. // pagination.current = 1;
  145. // emit('getPager', pagination.current, pageSize);
  146. // });
  147. // pagination.pageSize = pageSize;
  148. isPageSizeChange.value = true;
  149. };
  150. // 回到第一页
  151. const backFirstPage = () => {
  152. pagination.current = 1;
  153. emit('getPager', pagination.current, pagination.pageSize);
  154. };
  155. // 伸缩列
  156. const handleResizeColumn = (w, col) => {
  157. col.width = w;
  158. };
  159. // 选择每一项操作
  160. const selectEvent = (record, selected) => {
  161. if (selected) {
  162. state.selectedRows.push(record);
  163. state.selectedRowKeys.push(record.id);
  164. } else {
  165. let index = state.selectedRowKeys.indexOf(record.id);
  166. if (index >= 0) {
  167. state.selectedRows.splice(index, 1);
  168. state.selectedRowKeys.splice(index, 1);
  169. }
  170. }
  171. emit('getSelected', state);
  172. };
  173. // 点击以后全选当前分页数据
  174. const selectAllEvent = (selected, selectedRows, changeRows) => {
  175. if (selected) {
  176. changeRows.forEach(item => {
  177. state.selectedRows.push(item);
  178. state.selectedRowKeys.push(item.id);
  179. });
  180. } else {
  181. changeRows.forEach(item => {
  182. let index = state.selectedRowKeys.indexOf(item.id);
  183. if (index >= 0) {
  184. state.selectedRows.splice(index, 1);
  185. state.selectedRowKeys.splice(index, 1);
  186. }
  187. });
  188. }
  189. emit('getSelected', state);
  190. };
  191. // 清空选择
  192. const clear = (isClear = true) => {
  193. state.selectedRowKeys = [];
  194. state.selectedRows = [];
  195. if (isClear) {
  196. emit('getSelected', state);
  197. }
  198. };
  199. // 获取排序信息
  200. const tableChange = (pagination, filters, sorter) => {
  201. // pagination, filters 变化时也会触发所以对sorter进行判断限制执行
  202. if (Object.keys(sorter).length > 0) {
  203. if (sorter.field != lastSorter.field && sorter.order != lastSorter.order) {
  204. lastSorter.field = sorter.field;
  205. lastSorter.order = sorter.order;
  206. emit('getSorter', sorter);
  207. }
  208. if (sorter.field != lastSorter.field && sorter.order == lastSorter.order) {
  209. lastSorter.field = sorter.field;
  210. lastSorter.order = sorter.order;
  211. emit('getSorter', sorter);
  212. }
  213. if (sorter.field == lastSorter.field && sorter.order != lastSorter.order) {
  214. lastSorter.field = sorter.field;
  215. lastSorter.order = sorter.order;
  216. emit('getSorter', sorter);
  217. }
  218. }
  219. };
  220. // 暴露出方法
  221. defineExpose({ backFirstPage, clear });
  222. // 监听total变化
  223. watch(
  224. props,
  225. newData => {
  226. pagination.total = newData.total;
  227. extraHeight.value = newData.extraHeight;
  228. },
  229. { immediate: true, deep: true },
  230. );
  231. watch(
  232. () => props.selectedKeys,
  233. newData => {
  234. state.selectedRowKeys = newData;
  235. state.selectedRows = newData.map(item => props.dataSource.find(data => data.id === item));
  236. },
  237. { immediate: true, deep: true },
  238. );
  239. // 插槽的实例
  240. const slots = useSlots();
  241. const renderArr = Object.keys(slots);
  242. </script>
  243. <style scoped>
  244. .tablePaganations {
  245. width: 100%;
  246. margin-top: 8px;
  247. }
  248. .ant-table-striped :deep(.table-striped) td {
  249. background-color: #fafafa;
  250. }
  251. </style>