SortMixin.js 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /**
  2. * 通用多列排序 Mixin
  3. * 用法:在页面 data() 中声明 sortableColumns,在 loadList() 中加入 sortParams,
  4. * 在 el-table-column 的 slot="header" 中调用 this.sortHeader(col)。
  5. */
  6. export default {
  7. data() {
  8. return {
  9. sortState: [], // [{column, order:'asc'|'desc'}]
  10. }
  11. },
  12. computed: {
  13. sortLabel() {
  14. if (!this.sortState || this.sortState.length === 0) return ''
  15. const labels = this.sortableColumns || {}
  16. return this.sortState.map(s => {
  17. const label = labels[s.column] || s.column
  18. return (s.order === 'asc' ? label + '↑' : label + '↓')
  19. }).join(' > ')
  20. }
  21. },
  22. methods: {
  23. /**
  24. * 渲染排序列头 HTML 字符串(供 slot 内联使用)
  25. * 用法: <span v-html="sortHeader('name')"></span>
  26. */
  27. sortHeader(col, label) {
  28. const icon = this.sortIcon(col)
  29. const cls = this.sortClass(col)
  30. const safeCol = col.replace(/[."']/g, '')
  31. return `<span class="sort-header ${cls}" `
  32. + `onclick="window.__sortClick && window.__sortClick('${safeCol}', event)" `
  33. + `ondblclick="window.__sortToggle && window.__sortToggle('${safeCol}')" `
  34. + `>${label || col}${icon}</span>`
  35. },
  36. sortClass(col) {
  37. const s = this.sortState.find(x => x.column === col)
  38. if (!s) return ''
  39. return s.order === 'asc' ? 'sort-asc' : 'sort-desc'
  40. },
  41. sortIcon(col) {
  42. const s = this.sortState.find(x => x.column === col)
  43. if (!s) return ''
  44. return s.order === 'asc' ? ' ↑' : ' ↓'
  45. },
  46. onSortClick(col, event) {
  47. if (event.shiftKey) {
  48. this.shiftAppendSort(col)
  49. } else {
  50. this.setPrimarySort(col)
  51. }
  52. if (typeof this.loadList === 'function') this.loadList()
  53. },
  54. onSortToggle(col) {
  55. const idx = this.sortState.findIndex(s => s.column === col)
  56. if (idx >= 0) {
  57. this.sortState[idx].order = this.sortState[idx].order === 'asc' ? 'desc' : 'asc'
  58. } else {
  59. this.sortState = [{ column: col, order: 'asc' }]
  60. }
  61. if (typeof this.loadList === 'function') this.loadList()
  62. },
  63. setPrimarySort(col) {
  64. const idx = this.sortState.findIndex(s => s.column === col)
  65. if (idx >= 0) {
  66. const item = this.sortState.splice(idx, 1)[0]
  67. this.sortState.unshift(item)
  68. } else {
  69. this.sortState = [{ column: col, order: 'asc' }]
  70. }
  71. },
  72. shiftAppendSort(col) {
  73. const idx = this.sortState.findIndex(s => s.column === col)
  74. if (idx >= 0) {
  75. this.sortState[idx].order = this.sortState[idx].order === 'asc' ? 'desc' : 'asc'
  76. } else if (this.sortState.length < 3) {
  77. this.sortState.push({ column: col, order: 'asc' })
  78. }
  79. },
  80. clearSort() {
  81. this.sortState = []
  82. if (typeof this.loadList === 'function') this.loadList()
  83. },
  84. /** 将当前 sortState 注入到请求参数中 */
  85. applySortToParams(params) {
  86. if (this.sortState.length > 0) {
  87. params.sort = this.sortState
  88. }
  89. return params
  90. }
  91. }
  92. }