mobile.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <template>
  2. <div class="van-select">
  3. <van-field :model-value="inputValue"
  4. :placeholder="placeholder"
  5. :disabled="disabled"
  6. readonly
  7. is-link
  8. v-bind="$attrs"
  9. @click="openPopup"/>
  10. <van-popup v-model:show="show" position="bottom" style="height: 40%">
  11. <mobile-picker :config="config"
  12. :model-value="modelValue"
  13. :other-value="otherValue"
  14. :customFieldName="customFieldName"
  15. :columns="columns"
  16. @confirm="confirm"
  17. @cancel="cancel" />
  18. </van-popup>
  19. <!-- 多选如何处理 -->
  20. </div>
  21. </template>
  22. <script>
  23. import { Field as VanField, Popup as VanPopup } from 'vant'
  24. import MobilePicker from './mobile-picker.jsx'
  25. import { computed, ref } from 'vue'
  26. import { useFormInput, useOptions } from '@cip/components/hooks/form-input'
  27. import { formInputProps, fromInputEmits } from '../../form-input-props'
  28. import { isArray, isObject } from '@cip/utils/util'
  29. export default {
  30. inheritAttrs: false,
  31. components: { VanField, VanPopup, MobilePicker },
  32. props: formInputProps,
  33. emits: [...fromInputEmits],
  34. setup (props, context) {
  35. const { width, emitModelValue, emitOtherValue, ...formInput } = useFormInput(props, context)
  36. // 是否多选
  37. const multiple = computed(() => {
  38. return props.config?.multiple ?? false
  39. })
  40. const { optionProps, options, getValue, getModelValue, getOtherValue } = useOptions(props, multiple)
  41. // 另一个键
  42. const otherKey = computed(() => {
  43. return props.config?.otherKey ?? ''
  44. })
  45. // 面板按钮触发emit
  46. const emitInput = (value) => {
  47. if (!isArray(value) && isObject(value)) {
  48. value = value[customFieldName.value.value]
  49. }
  50. const modelValue = getModelValue(value)
  51. emitModelValue(modelValue)
  52. if (otherKey.value) {
  53. const otherValue = getOtherValue(modelValue, value)
  54. emitOtherValue(otherValue)
  55. }
  56. }
  57. // 内部代理一个Value
  58. const proxyValue = computed({
  59. get () {
  60. return getValue(props.modelValue)
  61. },
  62. set (value) {
  63. emitInput(value)
  64. }
  65. })
  66. // 打开面板
  67. const openPopup = () => {
  68. show.value = true
  69. }
  70. // 同级有没有children的情况下,级联选择器不出现下层
  71. const columns = computed(() => {
  72. if (customFieldName.value.children) {
  73. return addChildren(options.value)
  74. } else {
  75. return options.value
  76. }
  77. })
  78. // 都没有children的情况下,会多加一级,待处理
  79. const addChildren = (items) => {
  80. return items.map(i => {
  81. if (i.children) {
  82. addChildren(i.children)
  83. } else {
  84. i.children = []
  85. }
  86. return i
  87. })
  88. }
  89. // vant使用text代替label
  90. const customFieldName = computed(() => {
  91. const { label = 'label', value = 'value', children } = props.config?.optionProps ?? {}
  92. return { text: label, value, children }
  93. })
  94. // input输入框展示数据
  95. const inputValue = computed({
  96. get () {
  97. const value = getValue(props.modelValue)
  98. if (multiple.value) {
  99. return getOtherValue(props.modelValue, value)
  100. }
  101. const findItem = findChildrenItem(columns.value, value)
  102. return findItem ? findItem[customFieldName.value.text] : value
  103. }
  104. })
  105. // 对children进行递归
  106. const findChildrenItem = (array, value) => {
  107. // eslint-disable-next-line
  108. for(const item of array){
  109. if (item[customFieldName.value.value] === value) return item
  110. if (item[customFieldName.value.children] && item[customFieldName.value.children].length > 0) {
  111. const findItem = findChildrenItem(item[customFieldName.value.children], value)
  112. if (findItem) return findItem
  113. }
  114. }
  115. }
  116. // 面板按钮
  117. const show = ref(false)
  118. const confirm = (value) => {
  119. emitInput(value)
  120. show.value = false
  121. }
  122. const cancel = () => {
  123. show.value = false
  124. }
  125. return {
  126. ...formInput,
  127. multiple,
  128. columns,
  129. proxyValue,
  130. width,
  131. optionProps,
  132. show,
  133. customFieldName,
  134. inputValue,
  135. openPopup,
  136. confirm,
  137. cancel
  138. }
  139. }
  140. }
  141. </script>
  142. <style lang="less" scoped>
  143. .van-select{
  144. width: 100%;
  145. }
  146. </style>