Distpicker.vue 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. <template>
  2. <div :class="wrapper">
  3. <el-select v-model="currentProvince" :disabled="disabled || provinceDisabled" placeholder="省" @change="getCities">
  4. <el-option
  5. v-for="(item, index) in provinces"
  6. :value="item.name"
  7. :key="index"
  8. :label="item.name"/>
  9. </el-select>
  10. <template v-if="!onlyProvince">
  11. <el-select v-model="currentCity" :disabled="disabled || cityDisabled" placeholder="市" @change="getAreas">
  12. <el-option
  13. v-for="(item, index) in cities"
  14. :value="item.name"
  15. :key="index"
  16. :label="item.name"/>
  17. </el-select>
  18. <el-select v-if="!hideArea" v-model="currentArea" :disabled="disabled || areaDisabled" placeholder="区">
  19. <el-option
  20. v-for="(item, index) in areas "
  21. :value="item.name"
  22. :key="index"
  23. :label="item.name"/>
  24. </el-select>
  25. </template>
  26. </div>
  27. </template>
  28. <script>
  29. import DISTRICTS from './districts'
  30. export default {
  31. name: 'VDistpicker',
  32. props: {
  33. province: { type: [String, Number], default: '' },
  34. city: { type: [String, Number], default: '' },
  35. area: { type: [String, Number], default: '' },
  36. hideArea: { type: Boolean, default: false },
  37. onlyProvince: { type: Boolean, default: false },
  38. disabled: { type: Boolean, default: false },
  39. provinceDisabled: { type: Boolean, default: false },
  40. cityDisabled: { type: Boolean, default: false },
  41. areaDisabled: { type: Boolean, default: false },
  42. wrapper: { type: String, default: 'distpicker-address-wrapper' }
  43. },
  44. data() {
  45. return {
  46. provinces: [],
  47. cities: [],
  48. areas: [],
  49. currentProvince: '',
  50. currentCity: '',
  51. currentArea: ''
  52. }
  53. },
  54. watch: {
  55. currentProvince(value) {
  56. this.$emit('province', this.setData(value, this.provinces))
  57. if (this.onlyProvince) this.emit('selected')
  58. },
  59. currentCity(value) {
  60. this.$emit('city', this.setData(value, this.cities))
  61. if (this.hideArea) this.emit('selected')
  62. },
  63. currentArea(value) {
  64. this.$emit('area', this.setData(value, this.areas))
  65. this.emit('selected')
  66. },
  67. province(value) {
  68. this.currentProvince = this.province
  69. this.cities = this.getDataList(this.currentProvince, this.provinces)
  70. },
  71. city(value) {
  72. this.currentCity = this.city
  73. this.areas = this.getDataList(this.currentCity, this.cities)
  74. },
  75. area(value) {
  76. this.currentArea = this.area
  77. }
  78. },
  79. created() {
  80. this.provinces = DISTRICTS
  81. this.currentProvince = this.getNameValue(this.province, this.provinces)
  82. this.cities = this.province ? this.getDataList(this.province, this.provinces) : []
  83. this.currentCity = this.getNameValue(this.city, this.cities)
  84. this.areas = this.city ? this.getDataList(this.city, this.cities) : []
  85. this.currentArea = this.getNameValue(this.area, this.areas)
  86. },
  87. methods: {
  88. setData(value, list) {
  89. const valueObj = list ? list.find(item => item.name === value) : null
  90. return valueObj ? {
  91. code: valueObj.code,
  92. value: valueObj.name
  93. } : {
  94. code: '',
  95. value: ''
  96. }
  97. },
  98. emit(name) {
  99. const data = {
  100. province: this.setData(this.currentProvince, this.provinces)
  101. }
  102. if (!this.onlyProvince) {
  103. this.$set(data, 'city', this.setData(this.currentCity, this.cities))
  104. }
  105. if (!this.onlyProvince || this.hideArea) {
  106. this.$set(data, 'area', this.setData(this.currentArea, this.areas))
  107. }
  108. this.$emit(name, data)
  109. },
  110. getCities() {
  111. this.currentCity = ''
  112. this.currentArea = ''
  113. this.cities = this.getDataList(this.currentProvince, this.provinces)
  114. this.cleanList('areas')
  115. if (this.cities.length === 0) {
  116. this.emit('selected')
  117. }
  118. },
  119. getAreas() {
  120. this.currentArea = ''
  121. this.areas = this.getDataList(this.currentCity, this.cities)
  122. if (this.areas.length === 0) {
  123. this.emit('selected')
  124. }
  125. },
  126. /**
  127. * 获取数据信息
  128. * value code/name
  129. * list 上一级数据
  130. */
  131. getDataList(value, list) {
  132. const isCode = typeof value === 'number'
  133. for (let index = 0; index < list.length; index++) {
  134. const item = list[index]
  135. if ((isCode && item.code === value) ||
  136. !isCode && item.name === value) {
  137. return item.children
  138. }
  139. }
  140. },
  141. /**
  142. * 获取名称值
  143. * value code/name
  144. * list 当前类型数据
  145. */
  146. getNameValue(value, list) {
  147. if (typeof value === 'number') {
  148. for (let index = 0; index < list.length; index++) {
  149. const item = list[index]
  150. if (item.code === value) {
  151. return item.name
  152. }
  153. }
  154. }
  155. return value
  156. },
  157. cleanList(name) {
  158. this[name] = []
  159. }
  160. }
  161. }
  162. </script>
  163. <style lang="scss">
  164. .distpicker-address-wrapper {
  165. color: #9caebf;
  166. .el-select {
  167. width: 30%;
  168. }
  169. }
  170. </style>