table.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. const ButtonConfig = {
  2. add: {
  3. icon: 'el-icon-circle-plus-outline',
  4. label: '新增'
  5. }
  6. }
  7. // {
  8. // keepalive?: false,
  9. // singlePage?: false,
  10. // condition?: Object,
  11. // list: Function,
  12. // transform?: Function
  13. // buttons?: [
  14. // { type: String, icon: String, label: String, on: Function }
  15. // ],
  16. // filters?: [
  17. // { key: String, type: 'select', placeholder: String, ...SelectSchema },
  18. // { key: String, type: 'search', placeholder: String }
  19. // ],
  20. // cols: [
  21. // { prop: String, label: String, render?: Function | Array }
  22. // ]
  23. // }
  24. export default {
  25. provide () {
  26. return {
  27. table: this
  28. }
  29. },
  30. props: {
  31. schema: {
  32. type: Object,
  33. required: true
  34. },
  35. proxy: {
  36. type: Object,
  37. default: null
  38. }
  39. },
  40. data () {
  41. return {
  42. customOptions: null,
  43. buttons: null,
  44. filters: null
  45. }
  46. },
  47. computed: {
  48. hasHeader () {
  49. return this.$scopedSlots.header || this.buttons?.length || this.filters?.length
  50. },
  51. tableData () {
  52. const { transformData } = this.schema
  53. return transformData ? transformData(this.options.list) : this.options.list
  54. },
  55. options: {
  56. get () {
  57. return this.proxy || this.customOptions
  58. },
  59. set (val) {
  60. if (this.proxy) {
  61. this.$emit('update:proxy', val)
  62. } else {
  63. this.customOptions = val
  64. this.onPagination()
  65. }
  66. }
  67. },
  68. isManualPagination () {
  69. return this.schema.singlePage
  70. }
  71. },
  72. watch: {
  73. proxy () {
  74. this.queueStatus()
  75. },
  76. schema: {
  77. handler () {
  78. this.customOptions = this.createOptions(this.schema.condition)
  79. this.buttons = this.schema.buttons?.map(({ type, ...item }) => {
  80. return {
  81. ...ButtonConfig[type],
  82. ...item
  83. }
  84. })
  85. const filterMap = {}
  86. this.filters = this.schema.filters?.map(filter => {
  87. filterMap[filter.key] = filter
  88. return {
  89. ...filter,
  90. loading: false,
  91. loaded: !!filter.remote
  92. }
  93. })
  94. this.filterMap = filterMap
  95. this.queueStatus()
  96. },
  97. immediate: true
  98. }
  99. },
  100. activated () {
  101. if (this.schema.keepalive) {
  102. this.onPagination()
  103. }
  104. },
  105. methods: {
  106. queueStatus () {
  107. if (!this.$flushing) {
  108. this.$flushing = true
  109. this.$nextTick(this.flushStatus)
  110. }
  111. },
  112. flushStatus () {
  113. this.$flushing = false
  114. this.onPagination()
  115. },
  116. createOptions (condition) {
  117. return {
  118. loading: false,
  119. error: false,
  120. params: { pageSize: this.pageSize, pageNum: 1, ...condition },
  121. totalCount: 0,
  122. list: []
  123. }
  124. },
  125. filterInvokes (data) {
  126. return this.schema.invokes.filter(({ render }) => !render || render(data))
  127. },
  128. onPagination () {
  129. const options = this.options
  130. if (!options.loading) {
  131. options.loading = true
  132. const { list, transform } = this.schema
  133. list(options.params).then(
  134. ({ data, totalCount }) => {
  135. options.loading = false
  136. options.error = false
  137. options.totalCount = totalCount || data.length
  138. if (this.isManualPagination) {
  139. const { pageNum, pageSize } = options.params
  140. data = data.slice((pageNum - 1) * pageSize, pageNum * pageSize)
  141. }
  142. if (data.length === 0) {
  143. const { pageNum, pageSize } = options.params
  144. if (pageNum > 1) {
  145. return this.pageTo(totalCount ? Math.ceil(totalCount / pageSize) : 1)
  146. }
  147. }
  148. options.list = transform ? data.map(transform) : data
  149. },
  150. () => {
  151. options.loading = false
  152. options.error = true
  153. options.totalCount = 0
  154. options.list = []
  155. }
  156. )
  157. }
  158. },
  159. onClickButton ({ on }) {
  160. if (on) {
  161. on(this.options.params, this)
  162. }
  163. },
  164. onChange () {
  165. this.pageTo(1)
  166. },
  167. getInst () {
  168. return this.$refs.table
  169. },
  170. getData () {
  171. return this.options.list
  172. },
  173. setData (data) {
  174. this.options.list = data
  175. },
  176. info () {
  177. const options = this.options
  178. return {
  179. totalCount: options.totalCount,
  180. ...options.params
  181. }
  182. },
  183. getCondition () {
  184. return this.options.params
  185. },
  186. mergeCondition (condition) {
  187. const params = { ...this.options.params, pageNum: 1, ...condition }
  188. if (this.options.loading) {
  189. this.options = this.createOptions(params)
  190. } else {
  191. this.options.params = params
  192. }
  193. this.onPagination()
  194. },
  195. resetCondition (condition) {
  196. const params = this.options.params
  197. condition && Object.keys(condition).forEach(key => {
  198. const paramValue = params[key]
  199. if (paramValue != null && paramValue !== '') {
  200. const value = condition[key]
  201. const filter = this.filterMap[key]
  202. switch (filter?.key) {
  203. case 'select':
  204. if (paramValue !== value) {
  205. params[key] = filter.placeholder ? void 0 : value
  206. }
  207. break
  208. case 'search':
  209. if (new RegExp(paramValue).test(value)) {
  210. params[key] = ''
  211. }
  212. break
  213. default:
  214. params[key] = value
  215. break
  216. }
  217. }
  218. })
  219. this.onChange()
  220. },
  221. pageTo (pageNum) {
  222. if (pageNum >= 1) {
  223. return this.mergeCondition({ pageNum })
  224. }
  225. this.mergeCondition({ pageNum: this.options.params.pageNum })
  226. },
  227. decrease (count) {
  228. const options = this.options
  229. if (options.list.length <= count) {
  230. return this.pageTo(options.params.pageNum - 1)
  231. }
  232. this.pageTo()
  233. }
  234. }
  235. }