wk-area-picker.vue 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <template>
  2. <view :style="{height: height + 'px'}" class="wk-area-picker picker">
  3. <view class="picker-header">
  4. <view class="cancel" @click="handleCancel">
  5. 取消
  6. </view>
  7. <view class="picker-header-title" />
  8. <view class="confirm" @click="handleConfirm">
  9. 确认
  10. </view>
  11. </view>
  12. <picker-view
  13. v-if="showPicker"
  14. v-model="valueIndexArr"
  15. indicator-class="indicator-active"
  16. class="picker-body"
  17. @change="bindChange">
  18. <picker-view-column class="picker-body-column">
  19. <view v-for="(item,index) in list1" :key="index" class="picker-item">
  20. {{ item.name }}
  21. </view>
  22. </picker-view-column>
  23. <picker-view-column v-if="precisions >= 2" class="picker-body-column">
  24. <view v-for="(item,index) in list2" :key="index" class="picker-item">
  25. {{ item.name }}
  26. </view>
  27. </picker-view-column>
  28. <picker-view-column v-if="precisions >= 3" class="picker-body-column">
  29. <view v-for="(item,index) in list3" :key="index" class="picker-item">
  30. {{ item.name }}
  31. </view>
  32. </picker-view-column>
  33. </picker-view>
  34. </view>
  35. </template>
  36. <script>
  37. import AREA_DATA from './districts.js'
  38. const EMPTY_TEXT = '请选择'
  39. export default {
  40. name: 'WkAreaPicker',
  41. inject: ['popup'],
  42. props: {
  43. value: {
  44. type: Array,
  45. default: () => []
  46. },
  47. precisions: {
  48. type: Number,
  49. default: 3 // 1 省 2 省市 3 省市区
  50. },
  51. requiredFull: {
  52. type: Boolean,
  53. default: true // 是否允许选择空
  54. }
  55. },
  56. data() {
  57. return {
  58. height: 0,
  59. list1: [], // 第一列数据
  60. list2: [], // 第二列数据
  61. list3: [], // 第三列数据
  62. valueArr: [],
  63. valueIndexArr: [0, 0, 0],
  64. showPicker: false
  65. }
  66. },
  67. watch: {
  68. value: {
  69. handler() {
  70. this.setDefaultValueIndex()
  71. },
  72. deep: true,
  73. immediate: true
  74. }
  75. },
  76. mounted() {
  77. const that = this
  78. uni.getSystemInfo({
  79. success: res => {
  80. that.height = res.windowHeight * 0.4
  81. }
  82. })
  83. },
  84. methods: {
  85. getDataList(list, code = null) {
  86. if (!code) return AREA_DATA
  87. const findRes = list.find(o => o.code === Number(code)) || {}
  88. return findRes.children || []
  89. },
  90. initCom() {
  91. // 省列表数据
  92. this.list1 = AREA_DATA
  93. if (!this.requiredFull) {
  94. const findRes = this.list1.find(o => o.name === EMPTY_TEXT)
  95. if (!findRes) {
  96. this.list1.unshift({ name: EMPTY_TEXT, code: '' })
  97. }
  98. }
  99. this.getCityList()
  100. this.showPicker = false
  101. this.$nextTick(() => {
  102. this.showPicker = true
  103. })
  104. },
  105. /**
  106. * 市列表数据
  107. */
  108. getCityList() {
  109. let num = this.valueIndexArr[0] || 0
  110. if (num > this.list1.length - 1) {
  111. num = 0
  112. }
  113. this.valueIndexArr[0] = num
  114. const data = this.list1[num]
  115. this.list2 = data.children || []
  116. if (!this.requiredFull) {
  117. const findRes = this.list2.find(o => o.name === EMPTY_TEXT)
  118. if (!findRes) {
  119. this.list2.unshift({ name: EMPTY_TEXT, code: '' })
  120. }
  121. }
  122. this.getAreaList()
  123. },
  124. /**
  125. * 区列表数据
  126. */
  127. getAreaList() {
  128. let num = this.valueIndexArr[1] || 0
  129. if (num > this.list2.length - 1) {
  130. num = 0
  131. }
  132. this.valueIndexArr[1] = num
  133. const data = this.list2[num]
  134. this.list3 = data.children || []
  135. if (!this.requiredFull) {
  136. const findRes = this.list3.find(o => o.name === EMPTY_TEXT)
  137. if (!findRes) {
  138. this.list3.unshift({ name: EMPTY_TEXT, code: '' })
  139. }
  140. }
  141. },
  142. /**
  143. * 设置默认值
  144. */
  145. setDefaultValueIndex() {
  146. if (this.$isEmpty(this.value)) {
  147. this.valueIndexArr = [0, 0, 0]
  148. this.initCom()
  149. return
  150. }
  151. let list = AREA_DATA
  152. let arr = []
  153. this.value.forEach((val, index) => {
  154. if (!this.requiredFull) {
  155. const findRes = list.find(o => o.name === EMPTY_TEXT)
  156. if (!findRes) {
  157. list.unshift({ name: EMPTY_TEXT, code: '' })
  158. }
  159. }
  160. let findIndex = list.findIndex(o => {
  161. if (typeof val === 'string') return o.name === val
  162. return o.code == Number(val.code)
  163. })
  164. if (findIndex < 0) {
  165. findIndex = 0
  166. }
  167. arr.push(findIndex)
  168. list = list[findIndex].children || []
  169. })
  170. this.valueIndexArr = arr
  171. this.initCom()
  172. },
  173. bindChange({ detail }) {
  174. detail.value.forEach((item, index) => {
  175. if (this.valueIndexArr[index] !== item) {
  176. this.valueIndexArr[index] = item
  177. this.$nextTick(function() {
  178. if (index === 0) {
  179. this.$set(this.valueIndexArr, 1, 0)
  180. this.$set(this.valueIndexArr, 2, 0)
  181. this.getCityList()
  182. } else if (index === 1) {
  183. this.$set(this.valueIndexArr, 2, 0)
  184. this.getAreaList()
  185. }
  186. })
  187. }
  188. })
  189. },
  190. handleCancel() {
  191. this.popup.close()
  192. },
  193. handleConfirm() {
  194. let value = []
  195. this.valueIndexArr.forEach((v, i) => {
  196. const item = this[`list${i + 1}`][v]
  197. value.push({
  198. code: item.code,
  199. name: item.name,
  200. id: i + 1
  201. })
  202. })
  203. value = value
  204. .slice(0, this.precisions)
  205. .filter(o => o.name !== EMPTY_TEXT)
  206. this.$emit('input', value)
  207. this.$emit('select', value, () => {
  208. this.popup.close()
  209. })
  210. }
  211. }
  212. }
  213. </script>
  214. <style scoped lang="scss">
  215. .picker {
  216. width: 100%;
  217. background-color: white;
  218. display: flex;
  219. flex-direction: column;
  220. overflow: hidden;
  221. .picker-header {
  222. height: 70rpx;
  223. font-size: 26rpx;
  224. border-bottom: 1rpx solid $border-color;
  225. padding: 0 30rpx;
  226. @include left;
  227. .picker-header-title {
  228. flex: 1;
  229. }
  230. .cancel {
  231. color: #666666;
  232. }
  233. .confirm {
  234. color: $theme-color;
  235. }
  236. }
  237. .picker-body {
  238. flex: 1;
  239. padding: 0 30rpx;
  240. .picker-body-column {
  241. .picker-item {
  242. font-size: 26rpx;
  243. @include center;
  244. }
  245. }
  246. }
  247. }
  248. </style>