CrudTable.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <template>
  2. <div class="tab-container">
  3. <div class="tab-toolbar">
  4. <div class="tool-group">
  5. <el-button-group>
  6. <slot name="toolGroup"></slot>
  7. </el-button-group>
  8. </div>
  9. <slot name="toolMid"></slot>
  10. <div style="flex:1"></div>
  11. <el-icon class="is-loading" v-show="isLoading"><loading/></el-icon>
  12. <el-pagination
  13. v-model:current-page="pagination.currentPage"
  14. v-model:page-size="pagination.pageSize"
  15. :page-sizes="pageSizeOpts"
  16. :small="false"
  17. :disabled="false"
  18. :background="false"
  19. :layout="pageInfoOpts"
  20. :total="pagination.totalRows"
  21. />
  22. </div>
  23. <div class="tab-main">
  24. <el-table :data="tableDatas" style="width: 100%;height:100%;" border stripe highlight-current-row v-bind="$attrs" ref="$eltable">
  25. <slot name="tabColumns" :index-generate="indexGenerate"></slot>
  26. </el-table>
  27. </div>
  28. </div>
  29. </template>
  30. <script setup>
  31. import {reactive,ref,onMounted,toRaw,watch} from 'vue'
  32. import request from '../../utils/request'
  33. import { ElMessage } from "element-plus"
  34. const $eltable=ref(null)
  35. const emit=defineEmits(['loadSuccess'])
  36. const props=defineProps({
  37. pageSize:Number,
  38. pageSizeOpts:{
  39. type:Array,
  40. default:[10,20,30,50,100]
  41. },
  42. pageInfoOpts:String,
  43. url:String,
  44. datas:Array,
  45. initWhere:Object,
  46. autoLoad:{
  47. type:Boolean,
  48. default:true
  49. },
  50. autoPageSize:{
  51. type:Boolean,
  52. default:false
  53. }
  54. })
  55. const pagination=reactive({
  56. currentPage:1,
  57. pageSize:props.pageSize||10,
  58. totalRows:0,
  59. pageCount:1,
  60. watchReload:true //通过监听器重载
  61. })
  62. const isLoading=ref(false)
  63. const tableDatas=ref([])
  64. onMounted(async ()=>{
  65. if(props.autoPageSize){
  66. autoPageSize()
  67. }
  68. if(props.url&&props.autoLoad){
  69. query()
  70. }
  71. else{
  72. tableDatas.value=props.datas
  73. }
  74. })
  75. const autoPageSize=async ()=>{
  76. let pro= new Promise((resolve, reject)=>{
  77. setTimeout(()=>{
  78. //console.log('sleep 10')
  79. resolve(true)
  80. },10)
  81. })
  82. let rect=document.querySelector('.tab-main').getBoundingClientRect()
  83. while(!rect || rect.height<=0){
  84. await pro.catch(err=>{console.log(err)})
  85. rect=document.querySelector('.tab-main').getBoundingClientRect()
  86. }
  87. //console.log(rect)
  88. let rowCount=Math.ceil((rect.height-40)/42)
  89. rowCount=props.pageSizeOpts.find(val=>val>=rowCount)
  90. if(!rowCount){
  91. rowCount=100
  92. }
  93. toRaw(pagination).pageSize=rowCount
  94. }
  95. let _queryParam={}
  96. //只监听翻页、页size更改
  97. watch([
  98. ()=>pagination.currentPage,
  99. ()=>pagination.pageSize,
  100. ],
  101. ([newcp,newpz],[oldcp,oldpz])=>{
  102. if(pagination.watchReload){
  103. load(_queryParam)
  104. }
  105. })
  106. let getReqParam=(queryParams)=>{
  107. return Object.assign({},props.initWhere,toRaw(pagination),queryParams)
  108. }
  109. const getPageInfo=()=>{
  110. return toRaw(pagination)
  111. }
  112. const query=(queryParams)=>{
  113. pagination.watchReload=false
  114. pagination.currentPage=1 //新的查询页码重置为1,禁止通过监听自动查询,手动查询,便于外部接收查询状态
  115. return load(queryParams)
  116. }
  117. const load=async (queryParams)=>{
  118. //console.log('query...')
  119. isLoading.value=true
  120. try{
  121. let resp=await request({url: props.url,method: 'post',data: getReqParam(queryParams)})
  122. isLoading.value=false
  123. //console.log(resp)
  124. pagination.watchReload=true
  125. //pagination.currentPage=resp.currentPage
  126. tableDatas.value=null
  127. if(resp.code===0){
  128. tableDatas.value=resp.data.data
  129. pagination.totalRows=resp.data.totalRow
  130. pagination.pageCount = resp.data.pageCount
  131. _queryParam=queryParams||{}
  132. emit('loadSuccess',resp)
  133. return 0
  134. }
  135. else{
  136. ElMessage.error(resp.msg||"加载数据失败");
  137. return -1
  138. }
  139. }
  140. catch (e) {
  141. pagination.watchReload=true
  142. isLoading.value=false
  143. ElMessage.error("加载数据失败");
  144. console.log(e)
  145. return -1
  146. }
  147. }
  148. const indexGenerate=(index)=>{
  149. return (pagination.currentPage-1) * pagination.pageSize + index + 1
  150. }
  151. const addRow=(record)=>{
  152. if(!tableDatas.value){
  153. tableDatas.value=[]
  154. }
  155. tableDatas.value.push(record)
  156. }
  157. defineExpose({
  158. query,
  159. pagination,
  160. getPageInfo,
  161. addRow,
  162. getTableDataSet:()=>tableDatas,
  163. getSelectionRows:()=>$eltable.value.getSelectionRows()
  164. })
  165. </script>
  166. <style scoped>
  167. .tab-container{
  168. height:100%;
  169. }
  170. .tab-toolbar{
  171. height:50px;
  172. padding:10px 10px;
  173. box-sizing: border-box;
  174. background-color: #f0f9ff;
  175. display: flex;
  176. justify-content:space-between;
  177. border:1px solid #e3f1f8;
  178. border-bottom:0px;
  179. align-items: center;
  180. }
  181. .tab-toolbar .is-loading{
  182. margin:8px 20px;
  183. }
  184. .tab-main{
  185. height: calc(100% - 50px);
  186. border:0px;
  187. }
  188. </style>