XcTable.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <template>
  2. <el-table
  3. ref="tableRef"
  4. :data="tableData"
  5. style="width: 100%"
  6. @selection-change="selectionChange"
  7. @row-click="rowClick"
  8. :height="props.finalHeight === null ? visibleWindowSize.height - props.height : props.finalHeight"
  9. highlight-current-row
  10. @row-contextmenu="contextmenu"
  11. :row-key="props.rowKey"
  12. border
  13. @select-all="selectAll"
  14. :default-expand-all="props.defaultExpandAll"
  15. stripe>
  16. <slot/>
  17. </el-table>
  18. <el-pagination
  19. v-if="props.openPaging"
  20. :current-page="pageObject.currentPage"
  21. :page-size="pageObject.pageSize"
  22. :total="pageObject.total"
  23. :layout="props.layout"
  24. :small="props.small"
  25. :page-sizes="props.pageSizes"
  26. @current-change="currentChange"
  27. @size-change="sizeChange"/>
  28. </template>
  29. <script setup name='XcTable'>
  30. import {ElMessage} from "element-plus";
  31. import {BizException, ExceptionEnum} from "@/utils/BizException";
  32. import {getVisibleSize, visibleWindowSize} from "@/utils/window-size";
  33. import {onClickOutside} from "@vueuse/core";
  34. const props = defineProps({
  35. finalHeight: {
  36. type: Number,
  37. default: null
  38. },
  39. data: {
  40. type: Object,
  41. default: null
  42. },
  43. localData: {
  44. type: Array,
  45. default: null
  46. },
  47. rowKey: {
  48. type: String
  49. },
  50. height: {
  51. type: Number,
  52. default: 0
  53. },
  54. localPaging: {
  55. type: Boolean,
  56. default: false
  57. },
  58. openPaging: {
  59. type: Boolean,
  60. default: true
  61. },
  62. layout: {
  63. type: String,
  64. default: 'total, sizes, prev, pager, next, jumper'
  65. },
  66. small: {
  67. type: Boolean,
  68. default: false
  69. },
  70. pageSizes: {
  71. type: Array,
  72. default: [10, 20, 30, 100]
  73. },
  74. isArray: {
  75. type: Boolean,
  76. default: false
  77. },
  78. defaultExpandAll: {
  79. type: Boolean,
  80. default: true
  81. }
  82. })
  83. const emit = defineEmits([
  84. 'currentChange',
  85. 'sizeChange',
  86. 'rowClick',
  87. 'selectionChange',
  88. 'rowContextmenu'
  89. ])
  90. const tableRef = ref(null)
  91. let selection = $ref([])
  92. const tableData = computed(() => {
  93. if (!props.openPaging) {
  94. return pageObject.data
  95. }
  96. if (props.localPaging) {
  97. return props.data.data.slice((props.data.currentPage - 1) * props.data.pageSize, props.data.currentPage * props.data.pageSize)
  98. } else if (isLocalData) {
  99. return pageObject.data.slice((pageObject.currentPage - 1) * pageObject.pageSize, pageObject.currentPage * pageObject.pageSize)
  100. } else {
  101. return pageObject.data
  102. }
  103. })
  104. let flag = false // 默认 为全不选
  105. const selectAll = (selection) => {
  106. flag = !flag
  107. if (!flag) {
  108. // 在点击了全不选中 需要清空
  109. tableRef.value.clearSelection()
  110. return
  111. }
  112. let length = selection.length
  113. for (let i = 0; i < length; i++) {
  114. let item = selection[i]
  115. if (item.children) {
  116. toggleSelection(item.children, flag)
  117. }
  118. }
  119. }
  120. const toggleSelection = (row, selected) => {
  121. if (row) {
  122. for (let i = 0, len = row.length; i < len; i++) {
  123. tableRef.value.toggleRowSelection(row[i], selected)
  124. }
  125. }
  126. }
  127. const selectionChange = (selection) => {
  128. emit('selectionChange', selection)
  129. }
  130. const rowClick = (row, column, event) => {
  131. nextTick(() => {
  132. tableRef.value.toggleRowSelection(row)
  133. if (row.children) {
  134. for (let i = 0, len = row.children.length; i < len; i++) {
  135. tableRef.value.toggleRowSelection(row.children[i])
  136. }
  137. }
  138. })
  139. emit('rowClick', row, column, event);
  140. }
  141. /**
  142. * 取消选择或者多选
  143. * @param val
  144. */
  145. const toggleRowSelection = (...val) => {
  146. tableRef.value.toggleRowSelection(...val)
  147. }
  148. const currentChange = (val) => {
  149. if (isLocalData) {
  150. pageObject.currentPage = val
  151. } else {
  152. props.data.currentPage = val
  153. emit('currentChange', val)
  154. }
  155. tableRef.value.setScrollTop(0)
  156. }
  157. const sizeChange = (val) => {
  158. if (isLocalData) {
  159. pageObject.pageSize = val
  160. } else {
  161. props.data.pageSize = val
  162. props.data.currentPage = 1
  163. if (!props.localPaging) {
  164. props.data.total = 0
  165. }
  166. emit('sizeChange', val)
  167. }
  168. tableRef.value.setScrollTop(0)
  169. }
  170. const clearSelection = (msg = true) => {
  171. tableRef.value.clearSelection()
  172. if (msg) {
  173. ElMessage.success('清空成功。');
  174. }
  175. }
  176. const contextmenu = (row, column, event) => {
  177. event.returnValue = false
  178. event.preventDefault()
  179. emit('rowContextmenu', row)
  180. }
  181. /**
  182. * 获取选中的数据
  183. * @returns {*}
  184. */
  185. const getSelectionRows = () => {
  186. let data = tableRef.value.getSelectionRows()
  187. if (data.length > 0) {
  188. return data;
  189. }
  190. BizException(ExceptionEnum.MESSAGE_ERROR, "请先选择数据")
  191. }
  192. let pageObject = $ref({
  193. currentPage: 1,
  194. pageSize: 30,
  195. total: 0,
  196. data: []
  197. })
  198. let isLocalData = $ref(false)
  199. onMounted(() => {
  200. if (props.data !== null && props.localData !== null) {
  201. throw new Error('data 和 localData 不能同时使用')
  202. }
  203. if (props.localData !== null) {
  204. pageObject.data = props.localData
  205. pageObject.total = props.localData.length
  206. pageObject.currentPage = 1
  207. pageObject.pageSize = 30
  208. isLocalData = true
  209. watch(() => props.localData, () => {
  210. pageObject.data = props.localData
  211. pageObject.total = props.localData.length
  212. })
  213. } else {
  214. pageObject = props.data
  215. }
  216. })
  217. defineExpose({clearSelection, getSelectionRows, toggleRowSelection})
  218. </script>
  219. <style scoped>
  220. </style>