CommonTable.vue 6.3 KB

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