select-region.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <template>
  2. <view class="container">
  3. <view v-if="isLoading" class="loading">
  4. <u-loading mode="circle"></u-loading>
  5. </view>
  6. <view v-else class="field-body" @click="handleSelect()">
  7. <view class="field-value oneline-hide">{{ valueText ? valueText : placeholder }}</view>
  8. </view>
  9. <u-select v-model="show" mode="mutil-column-auto" :list="options" :default-value="defaultValue" @confirm="onConfirm"></u-select>
  10. </view>
  11. </template>
  12. <script>
  13. import Emitter from '@/uni_modules/vk-uview-ui/libs/util/emitter'
  14. import {isEmpty} from '@/utils/util'
  15. import RegionModel from '@/common/model/Region'
  16. // 根据选中的value集获取索引集keys
  17. // 用于设置默认选中
  18. const findOptionsKey = (data, searchValue, deep = 1, keys = []) => {
  19. const index = data.findIndex((item) => item.value === searchValue[deep - 1])
  20. if (index > -1) {
  21. keys.push(index)
  22. if (data[index].children) {
  23. findOptionsKey(data[index].children, searchValue, ++deep, keys)
  24. }
  25. }
  26. return keys
  27. }
  28. export default {
  29. name: 'SelectRegion',
  30. mixins: [Emitter],
  31. emits: ['update:modelValue'],
  32. props: {
  33. // 当前选中的值
  34. modelValue: {
  35. type: Array,
  36. default: () => {
  37. return []
  38. }
  39. },
  40. // 未选中时的提示文字
  41. placeholder: {
  42. type: String,
  43. default: '请选择省/市/区'
  44. }
  45. },
  46. data() {
  47. return {
  48. // 正在加载
  49. isLoading: true,
  50. // 是否显示
  51. show: false,
  52. // 默认选中的值
  53. defaultValue: [],
  54. // 选中项内容(文本展示)
  55. valueText: '',
  56. // 级联选择器数据
  57. options: []
  58. }
  59. },
  60. watch: {
  61. // 监听当前选中的值
  62. modelValue(val) {
  63. // 设置默认选中的值
  64. this.valueText = val.map((item) => item.label).join('/')
  65. this.setDefaultValue(val)
  66. // 将当前的值发送到 u-form-item 进行校验
  67. // this.dispatch('u-form-item', 'on-form-change', val)
  68. }
  69. },
  70. created() {
  71. // 获取地区数据 (同步)
  72. this.getTreeDataSync()
  73. },
  74. methods: {
  75. // 打开选择器
  76. handleSelect() {
  77. this.show = true
  78. },
  79. // // 获取地区数据 (异步)
  80. // getTreeData() {
  81. // const app = this
  82. // app.isLoading = true
  83. // RegionModel.getTreeData()
  84. // .then(regions => {
  85. // // 格式化级联选择器数据
  86. // app.options = app.getOptions(regions)
  87. // app.setDefaultValue(app.modelValue)
  88. // })
  89. // .finally(() => app.isLoading = false)
  90. // },
  91. // 获取地区数据 (同步)
  92. getTreeDataSync() {
  93. const app = this
  94. const regions = RegionModel.getTreeDataSync()
  95. app.options = app.getOptions(regions)
  96. app.setDefaultValue(app.modelValue)
  97. app.isLoading = false
  98. },
  99. // 确认选择后的回调
  100. onConfirm(value) {
  101. // 记录选中的值
  102. this.$emit('update:modelValue', value)
  103. },
  104. /**
  105. * 设置默认选中的值
  106. * 该操作是为了每次打开选择器时聚焦到上次选择
  107. * @param {Object} value
  108. */
  109. setDefaultValue(value) {
  110. console.log(value, 'value')
  111. if (value) {
  112. const options = this.options
  113. const values = value.map((item) => item.value)
  114. this.defaultValue = options.length ? findOptionsKey(options, values) : []
  115. }
  116. },
  117. /**
  118. * 格式化级联选择器数据
  119. * @param {*} regions 地区数据
  120. */
  121. getOptions(regions) {
  122. const {getOptions, getChildren} = this
  123. const options = []
  124. for (const index in regions) {
  125. const item = regions[index]
  126. const children = getChildren(item)
  127. const optionItem = {
  128. value: item.id,
  129. label: item.name
  130. }
  131. if (children !== false) {
  132. optionItem.children = getOptions(children)
  133. }
  134. options.push(optionItem)
  135. }
  136. return options
  137. },
  138. // 获取子集地区
  139. getChildren(item) {
  140. if (item.city) {
  141. return item.city
  142. }
  143. if (item.region) {
  144. return item.region
  145. }
  146. return false
  147. },
  148. // 根据省市区名称获取optionItem
  149. getOptionItemByNames({provinceName, cityName, countyName}) {
  150. const app = this
  151. const data = []
  152. app.options.forEach((provinceItem) => {
  153. if (provinceItem.label == provinceName || `${provinceItem.label}市` == provinceName) {
  154. data.push({label: provinceItem.label, value: provinceItem.value})
  155. provinceItem.children.forEach((cityItem) => {
  156. if (cityItem.label == cityName) {
  157. data.push({label: cityItem.label, value: cityItem.value})
  158. cityItem.children.forEach((countyItem) => {
  159. if (countyItem.label == countyName) {
  160. data.push({label: countyItem.label, value: countyItem.value})
  161. }
  162. })
  163. }
  164. })
  165. }
  166. })
  167. return data
  168. }
  169. }
  170. }
  171. </script>
  172. <style lang="scss" scoped>
  173. .container {
  174. width: 100%;
  175. }
  176. .loading {
  177. padding-left: 10rpx;
  178. // text-align: center;
  179. }
  180. </style>