index.jsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import { ref, onMounted, watch, nextTick, computed } from 'vue'
  2. import { ElDropdown, ElDropdownMenu, ElDropdownItem } from 'element-plus'
  3. import CipButtonText from '@cip/components/cip-button-text'
  4. import CipButton from '@cip/components/cip-button'
  5. import { useTable } from '../hooks/use-table'
  6. import './index.less'
  7. import { getUsingConfig } from '@cip/utils/util'
  8. const getButtonInfo = (vnode) => {
  9. if (vnode.component) {
  10. const text = vnode.component.slots.default()
  11. // console.log(vnode.component.emitsOptions.click)
  12. const info = { ...vnode.component.ctx._.props, ...vnode.component.ctx._.attrs }
  13. const { onClick = (e) => vnode.component.ctx._.emit('click', e) } = info
  14. return {
  15. ...info,
  16. onClick,
  17. text
  18. }
  19. }
  20. return {}
  21. }
  22. const RenderComponent = (props) => {
  23. const list = props.buttonList // .value
  24. let dropDownNode
  25. let buttonNodeList = list
  26. if (list.length > props.limit) {
  27. buttonNodeList = list.slice(0, props.limit - 1)
  28. dropDownNode = <ElDropdown style={'margin-left: 8px'} size={props.size}>
  29. {{
  30. default: () => props.buttonComp === 'button'
  31. ? <CipButton square={true} icon={'el-icon-arrow-down'}/>
  32. : <CipButtonText>更多<i class={'el-icon-caret-bottom'}/></CipButtonText>,
  33. dropdown: () => <ElDropdownMenu>
  34. {
  35. list.slice(props.limit - 1).map(item => {
  36. const { onClick, text, disabled } = getButtonInfo(item)
  37. return <ElDropdownItem onClick={onClick} disabled={disabled}>{text}</ElDropdownItem>
  38. })
  39. }
  40. </ElDropdownMenu>
  41. }}
  42. </ElDropdown>
  43. }
  44. const result = buttonNodeList.map(item => {
  45. const { onClick, text, type, icon, disabled } = getButtonInfo(item)
  46. const ButtonComponent = props.buttonComp === 'button' ? CipButton : CipButtonText
  47. return <ButtonComponent type={type} disabled={disabled} icon={icon} onClick={onClick}>{text}</ButtonComponent>
  48. })
  49. if (dropDownNode) {
  50. result.push(dropDownNode)
  51. }
  52. return result
  53. }
  54. export default {
  55. name: 'CipTableHandler',
  56. props: {
  57. limit: { type: Number },
  58. row: { type: Object, required: true },
  59. buttonComp: { type: String, default: 'text', validate: (val) => ['text', 'button'].includes(val) }
  60. },
  61. setup (props, { slots }) {
  62. const cipTable = useTable()
  63. const buttonList = ref([])
  64. const originRef = ref()
  65. const handlerLimit = computed(() => {
  66. return getUsingConfig(props.limit, props.buttonComp === 'text' ? 3 : 4)
  67. })
  68. let vnodeList = []
  69. onMounted(() => {
  70. watch(() => props.row, () => {
  71. nextTick().then(() => collectButtons())
  72. }, { immediate: true, deep: true })
  73. })
  74. const collectButtons = () => {
  75. buttonList.value = []
  76. vnodeList.forEach(vnode => getButtons(vnode))
  77. }
  78. const getButtons = (vnode) => {
  79. if (vnode.shapeFlag === 16) { // 数组
  80. vnode.children.forEach(v => getButtons(v))
  81. }
  82. if (vnode.shapeFlag === 17) { // 原生的dom
  83. vnode.children.forEach(v => getButtons(v))
  84. }
  85. if (vnode.shapeFlag === 36) { // 组件
  86. const componentName = (vnode.type.name || '').toLowerCase()
  87. if (componentName.indexOf('button') > -1) {
  88. buttonList.value.push(vnode)
  89. } else {
  90. if (vnode.component) {
  91. const children = vnode.component.subTree.children || []
  92. children.forEach(v => getButtons(v))
  93. }
  94. }
  95. }
  96. }
  97. return () => {
  98. vnodeList = slots.default?.()
  99. return <div class={'cip-table-handler'}>
  100. <div ref={el => { originRef.value = el }} style={'display: none'}>{vnodeList}</div>
  101. <RenderComponent limit={handlerLimit.value} size={cipTable.size} buttonList={buttonList.value} buttonComp={props.buttonComp} />
  102. </div>
  103. }
  104. }
  105. }