index.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <template>
  2. <view class="jnpf-cascader">
  3. <selectBox v-model="innerValue" :placeholder="placeholder" @openSelect="openSelect" :select-open="selectShow">
  4. </selectBox>
  5. <Tree v-if="selectShow" v-model="selectShow" :multiple="multiple" :props="props" :selectList="selectList"
  6. :options="options" :selectedId="!multiple ? [modelValue] : modelValue" :filterable='filterable'
  7. :selectData="selectData" :clearable="clearable" :showAllLevels="showAllLevels" @close="handleClose"
  8. @confirm="handleConfirm" />
  9. </view>
  10. </template>
  11. <script>
  12. import selectBox from '@/components/selectBox'
  13. import Tree from './Tree';
  14. export default {
  15. name: 'jnpf-cascader',
  16. components: {
  17. Tree,
  18. selectBox
  19. },
  20. props: {
  21. modelValue: {
  22. default: ''
  23. },
  24. placeholder: {
  25. type: String,
  26. default: '请选择'
  27. },
  28. options: {
  29. type: Array,
  30. default: () => []
  31. },
  32. props: {
  33. type: Object,
  34. default: () => ({
  35. label: 'fullName',
  36. value: 'id',
  37. children: 'children'
  38. })
  39. },
  40. disabled: {
  41. type: Boolean,
  42. default: false
  43. },
  44. multiple: {
  45. type: Boolean,
  46. default: false
  47. },
  48. showAllLevels: {
  49. type: Boolean,
  50. default: true
  51. },
  52. filterable: {
  53. type: Boolean,
  54. default: false
  55. },
  56. clearable: {
  57. type: Boolean,
  58. default: false
  59. },
  60. },
  61. watch: {
  62. modelValue: {
  63. handler(val) {
  64. this.setDefault(this.modelValue)
  65. },
  66. immediate: true
  67. },
  68. options: {
  69. handler(val) {
  70. this.setDefault(this.modelValue)
  71. },
  72. deep: true
  73. }
  74. },
  75. data() {
  76. return {
  77. selectShow: false,
  78. innerValue: '',
  79. selectList: [],
  80. selectData: [],
  81. allList: []
  82. }
  83. },
  84. methods: {
  85. async setDefault(value) {
  86. this.innerValue = ''
  87. this.selectData = []
  88. this.selectList = []
  89. if (!value || !value?.length) return
  90. this.allList = await this.treeToArray(value)
  91. if (!this.multiple) value = [value]
  92. let txt = []
  93. for (let i = 0; i < value.length; i++) {
  94. let val = uni.$u.deepClone(value[i])
  95. for (let j = 0; j < val.length; j++) {
  96. inner: for (let k = 0; k < this.allList.length; k++) {
  97. if (val[j] === this.allList[k][this.props.value]) {
  98. val[j] = this.allList[k][this.props.label];
  99. this.selectData.push(this.allList[k])
  100. break;
  101. }
  102. }
  103. }
  104. txt.push(val)
  105. }
  106. this.selectList = txt.map(o => this.showAllLevels ? o.join('/') : o[o.length - 1])
  107. this.innerValue = this.selectList.join()
  108. },
  109. async treeToArray() {
  110. let options = uni.$u.deepClone(this.options)
  111. let list = []
  112. const loop = (options) => {
  113. for (let i = 0; i < options.length; i++) {
  114. const item = options[i]
  115. list.push(item)
  116. if (item[this.props.children] && Array.isArray(item[this.props.children])) {
  117. loop(item[this.props.children])
  118. }
  119. }
  120. }
  121. loop(options)
  122. return list
  123. },
  124. openSelect() {
  125. if (this.disabled) return
  126. this.selectShow = true
  127. },
  128. handleConfirm(e, selectId, selectData) {
  129. this.selectList = e;
  130. this.innerValue = e.join()
  131. if (!this.multiple) {
  132. this.$emit('update:modelValue', selectId[0])
  133. this.$emit('change', selectId[0], selectData[0])
  134. } else {
  135. this.$emit('update:modelValue', selectId)
  136. this.$emit('change', selectId, selectData)
  137. }
  138. },
  139. handleClose() {
  140. this.selectShow = false
  141. }
  142. }
  143. }
  144. </script>
  145. <style lang="scss" scoped>
  146. .jnpf-cascader {
  147. width: 100%;
  148. }
  149. </style>