u-city-select.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. <template>
  2. <u-popup v-model="value" :closeable="true" :mask="true" :maskCloseAble="maskCloseAble" :popup="false" :safe-area-inset-bottom="true"
  3. :z-index="uZIndex" close-icon-color="#ffffff" mode="bottom" @close="close">
  4. <u-tabs v-if="value" ref="tabs" :current="tabsIndex" :is-scroll="true" :list="genTabsList"
  5. @change="tabsChange"></u-tabs>
  6. <view class="area-box">
  7. <view :class="{ 'change':isChange }" class="u-flex">
  8. <view class="area-item">
  9. <view class="u-padding-10 u-bg-gray" style="height: 100%;">
  10. <scroll-view :scroll-y="true" style="height: 100%">
  11. <u-cell-group>
  12. <u-cell-item v-for="(item,index) in provinces" :key="index" :arrow="false" :index="index"
  13. :title="item.label"
  14. @click="provinceChange">
  15. <u-icon v-if="isChooseP&&province===index" slot="right-icon" name="checkbox-mark" size="34"></u-icon>
  16. </u-cell-item>
  17. </u-cell-group>
  18. </scroll-view>
  19. </view>
  20. </view>
  21. <view class="area-item">
  22. <view class="u-padding-10 u-bg-gray" style="height: 100%;">
  23. <scroll-view :scroll-y="true" style="height: 100%">
  24. <u-cell-group v-if="isChooseP">
  25. <u-cell-item v-for="(item,index) in citys" :key="index" :arrow="false" :index="index"
  26. :title="item.label"
  27. @click="cityChange">
  28. <u-icon v-if="isChooseC&&city===index" slot="right-icon" name="checkbox-mark" size="34"></u-icon>
  29. </u-cell-item>
  30. </u-cell-group>
  31. </scroll-view>
  32. </view>
  33. </view>
  34. <view class="area-item">
  35. <view class="u-padding-10 u-bg-gray" style="height: 100%;">
  36. <scroll-view :scroll-y="true" style="height: 100%">
  37. <u-cell-group v-if="isChooseC">
  38. <u-cell-item v-for="(item,index) in areas" :key="index" :arrow="false" :index="index"
  39. :title="item.label"
  40. @click="areaChange">
  41. <u-icon v-if="isChooseA&&area===index" slot="right-icon" name="checkbox-mark" size="34"></u-icon>
  42. </u-cell-item>
  43. </u-cell-group>
  44. </scroll-view>
  45. </view>
  46. </view>
  47. </view>
  48. </view>
  49. </u-popup>
  50. </template>
  51. <script>
  52. import provinces from "uview-ui/libs/util/province.js";
  53. import citys from "uview-ui/libs/util/city.js";
  54. import areas from "uview-ui/libs/util/area.js";
  55. /**
  56. * city-select 省市区级联选择器
  57. * @property {String Number} z-index 弹出时的z-index值(默认1075)
  58. * @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭Picker(默认true)
  59. * @property {String} default-region 默认选中的地区,中文形式
  60. * @property {String} default-code 默认选中的地区,编号形式
  61. */
  62. export default {
  63. name: 'u-city-select',
  64. props: {
  65. // 通过双向绑定控制组件的弹出与收起
  66. value: {
  67. type: Boolean,
  68. default: false
  69. },
  70. // 默认显示的地区,可传类似["河北省", "秦皇岛市", "北戴河区"]
  71. defaultRegion: {
  72. type: Array,
  73. default() {
  74. return [];
  75. }
  76. },
  77. // 默认显示地区的编码,defaultRegion和areaCode同时存在,areaCode优先,可传类似["13", "1303", "130304"]
  78. areaCode: {
  79. type: Array,
  80. default() {
  81. return [];
  82. }
  83. },
  84. // 是否允许通过点击遮罩关闭Picker
  85. maskCloseAble: {
  86. type: Boolean,
  87. default: true
  88. },
  89. // 弹出的z-index值
  90. zIndex: {
  91. type: [String, Number],
  92. default: 0
  93. }
  94. },
  95. data() {
  96. return {
  97. cityValue: "",
  98. isChooseP: false, //是否已经选择了省
  99. province: 0, //省级下标
  100. provinces: provinces,
  101. isChooseC: false, //是否已经选择了市
  102. city: 0, //市级下标
  103. citys: citys[0],
  104. isChooseA: false, //是否已经选择了区
  105. area: 0, //区级下标
  106. areas: areas[0][0],
  107. tabsIndex: 0,
  108. }
  109. },
  110. mounted() {
  111. this.init();
  112. },
  113. computed: {
  114. isChange() {
  115. return this.tabsIndex > 1;
  116. },
  117. genTabsList() {
  118. let tabsList = [{
  119. name: "请选择"
  120. }];
  121. if (this.isChooseP) {
  122. tabsList[0]['name'] = this.provinces[this.province]['label'];
  123. tabsList[1] = {
  124. name: "请选择"
  125. };
  126. }
  127. if (this.isChooseC) {
  128. tabsList[1]['name'] = this.citys[this.city]['label'];
  129. tabsList[2] = {
  130. name: "请选择"
  131. };
  132. }
  133. if (this.isChooseA) {
  134. tabsList[2]['name'] = this.areas[this.area]['label'];
  135. }
  136. return tabsList;
  137. },
  138. uZIndex() {
  139. // 如果用户有传递z-index值,优先使用
  140. return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
  141. }
  142. },
  143. methods: {
  144. init() {
  145. if (this.areaCode.length == 3) {
  146. this.setProvince("", this.areaCode[0]);
  147. this.setCity("", this.areaCode[1]);
  148. this.setArea("", this.areaCode[2]);
  149. } else if (this.defaultRegion.length == 3) {
  150. this.setProvince(this.defaultRegion[0], "");
  151. this.setCity(this.defaultRegion[1], "");
  152. this.setArea(this.defaultRegion[2], "");
  153. }
  154. ;
  155. },
  156. setProvince(label = "", value = "") {
  157. this.provinces.map((v, k) => {
  158. if (value ? v.value == value : v.label == label) {
  159. this.provinceChange(k);
  160. }
  161. })
  162. },
  163. setCity(label = "", value = "") {
  164. this.citys.map((v, k) => {
  165. if (value ? v.value == value : v.label == label) {
  166. this.cityChange(k);
  167. }
  168. })
  169. },
  170. setArea(label = "", value = "") {
  171. this.areas.map((v, k) => {
  172. if (value ? v.value == value : v.label == label) {
  173. this.isChooseA = true;
  174. this.area = k;
  175. }
  176. })
  177. },
  178. close() {
  179. this.$emit('input', false);
  180. },
  181. tabsChange(index) {
  182. this.tabsIndex = index;
  183. },
  184. provinceChange(index) {
  185. this.isChooseP = true;
  186. this.isChooseC = false;
  187. this.isChooseA = false;
  188. this.province = index;
  189. this.citys = citys[index];
  190. this.tabsIndex = 1;
  191. },
  192. cityChange(index) {
  193. this.isChooseC = true;
  194. this.isChooseA = false;
  195. this.city = index;
  196. this.areas = areas[this.province][index];
  197. this.tabsIndex = 2;
  198. },
  199. areaChange(index) {
  200. this.isChooseA = true;
  201. this.area = index;
  202. let result = {};
  203. result.province = this.provinces[this.province];
  204. result.city = this.citys[this.city];
  205. result.area = this.areas[this.area];
  206. this.$emit('city-change', result);
  207. this.close();
  208. }
  209. }
  210. }
  211. </script>
  212. <style lang="scss">
  213. .area-box {
  214. width: 100%;
  215. overflow: hidden;
  216. height: 800 rpx;
  217. > view {
  218. width: 150%;
  219. transition: transform 0.3s ease-in-out 0s;
  220. transform: translateX(0);
  221. &.change {
  222. transform: translateX(-33.3333333%);
  223. }
  224. }
  225. .area-item {
  226. width: 33.3333333%;
  227. height: 800 rpx;
  228. }
  229. }
  230. </style>