index.jsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { computed, watch, onMounted } from 'vue'
  2. import { ElTree } from 'element-plus'
  3. import { useFormInput, useOptions, useInputProps, useElementFormEvent } from '@cip/components/hooks/form-input'
  4. import { formInputProps, fromInputEmits } from '../../form-input-props'
  5. import { depthFirstSearchTree, isNotEmpty } from '@cip/utils/util'
  6. export default {
  7. props: formInputProps,
  8. emits: fromInputEmits,
  9. setup (props, context) {
  10. const { securityConfig, width, proxyValue, inputRef, updateStream } = useFormInput(props, context, { maxOtherKey: 2 })
  11. const { handleChange } = useElementFormEvent()
  12. // 注意nodeKey的功能由optionProps.value.value提供
  13. const inputProps = useInputProps(props, [
  14. 'lazy',
  15. 'load',
  16. 'defaultExpandAll'
  17. ])
  18. const multiple = computed(() => {
  19. return securityConfig.value.multiple // 多选树
  20. })
  21. const { optionProps, options } = useOptions(props, multiple)
  22. const getLeafCheckedNodes = (checkedNodes) => {
  23. return checkedNodes.filter(v => !v[optionProps.value.children] || v[optionProps.value.children].length === 0)
  24. }
  25. const getPathValue = (modelValue, options, optionProps) => { // 注意此处的options,optionProps与 useOptions提供的不是同一个
  26. const checkedPathNodes = modelValue.map(value => {
  27. for (let i = 0; i < options.length; i++) {
  28. // 获取路径中的最后一个 注意最后的pop方法
  29. const path = depthFirstSearchTree(options[i], value, optionProps.value, optionProps.children)
  30. if (path) {
  31. return path.map(node => node[optionProps.value])
  32. }
  33. }
  34. })
  35. return checkedPathNodes
  36. }
  37. const handleCheck = (data, { checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys }) => {
  38. const leafCheckedNodes = getLeafCheckedNodes(checkedNodes)
  39. const modelValue = leafCheckedNodes.map(v => v[optionProps.value.value])
  40. context.emit('update:modelValue', modelValue)
  41. updateStream.appendValue(modelValue)
  42. const pathValue = getPathValue(modelValue, options.value, optionProps.value)
  43. updateStream.appendOtherValue(pathValue)
  44. updateStream.appendOtherValue({ checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys }, 2)
  45. updateStream.end()
  46. handleChange(modelValue)
  47. }
  48. //
  49. const setChecked = (optionsValue = [], nextChecked = []) => {
  50. const checkedNodes = nextChecked.map(value => {
  51. for (let i = 0; i < optionsValue.length; i++) {
  52. // 获取路径中的最后一个 注意最后的pop方法
  53. const path = depthFirstSearchTree(optionsValue[i], value, optionProps.value.value, optionProps.value.children)
  54. if (path) {
  55. return path.pop()
  56. }
  57. }
  58. })
  59. const checkedKeys = checkedNodes
  60. .filter(v => isNotEmpty(v))
  61. .filter(v => !v[optionProps.value.children] || v[optionProps.value.children].length === 0)
  62. .map(v => v[optionProps.value.value])
  63. inputRef.value.setCheckedKeys(checkedKeys)
  64. }
  65. onMounted(() => {
  66. watch([proxyValue, options], ([value, optionsValue]) => {
  67. setChecked(optionsValue, value)
  68. }, { immediate: true, deep: true })
  69. })
  70. return () => <div class="cip-tree"><ElTree
  71. {...inputProps.value}
  72. ref={inputRef}
  73. style={{ width: width.value }}
  74. props={optionProps.value}
  75. nodeKey={optionProps.value.value}
  76. showCheckbox={multiple.value}
  77. data={options.value}
  78. onCheck={(data, node) => handleCheck(data, node)}
  79. />
  80. </div>
  81. }
  82. }