app-area-picker.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. <template>
  2. <view class="dir-left-nowrap cross-center">
  3. <!-- #ifdef MP-WEIXIN || MP-BAIDU || H5 -->
  4. <picker class="box-grow-1 area-picker-left"
  5. mode="multiSelector"
  6. @change="bindMultiPickerChange"
  7. @columnchange="bindMultiPickerColumnChange"
  8. :value="multiIndex"
  9. range-key="name"
  10. :range="multiArray">
  11. <text v-if="place!==`请选择`" class="address-name-color">{{place}}</text>
  12. <text v-else class="address-place-name-color">{{place}}</text>
  13. </picker>
  14. <!-- #endif -->
  15. <!-- #ifdef MP-ALIPAY || MP-TOUTIAO -->
  16. <view class="area-picker-left" @click="showAreaPicker">
  17. <text v-if="place!==`请选择`" class="address-name-color">{{place}}</text>
  18. <text v-else class="address-place-name-color">{{place}}</text>
  19. </view>
  20. <view class="area-picker" :class="area_picker_show">
  21. <view class="area-picker-bg" bindtap="hideAreaPicker">
  22. <scroll-view></scroll-view>
  23. </view>
  24. <view class="area-picker-body">
  25. <scroll-view>
  26. <view class="area-picker-top">
  27. <text class="area-picker-cancel" @click="hideAreaPicker">取消</text>
  28. <text class="area-picker-confirm" @click="areaPickerConfirm">确认</text>
  29. </view>
  30. <view class="area-picker-row">
  31. <picker-view v-if="multiIndex && multiIndex.length" indicator-style="height: 50px" style="width: 100%; height: 250px;"
  32. :value="multiIndex" @change="areaPickerChange">
  33. <picker-view-column>
  34. <view v-if="multiArray[0]" v-for="(item,index) in multiArray[0]" :key="index"
  35. style="line-height: 50px;height: 50px;text-align: center">{{item.name}}
  36. </view>
  37. </picker-view-column>
  38. <picker-view-column>
  39. <view v-if="multiArray[1]" v-for="(item,index) in multiArray[1]" :key="index"
  40. style="line-height: 50px;height: 50px;text-align: center">{{item.name}}
  41. </view>
  42. </picker-view-column>
  43. <picker-view-column>
  44. <view v-if="multiArray[2]" v-for="(item,index) in multiArray[2]" :key="index"
  45. style="line-height: 50px;height: 50px;text-align: center">{{item.name}}
  46. </view>
  47. </picker-view-column>
  48. </picker-view>
  49. </view>
  50. </scroll-view>
  51. </view>
  52. </view>
  53. <!-- #endif -->
  54. <image class="box-grow-0 arrow-image" src="/static/image/icon/arrow-right.png"></image>
  55. </view>
  56. </template>
  57. <script>
  58. export default {
  59. name: "app-area-picker",
  60. props: {
  61. ids: {
  62. type: Array,
  63. default: function () {
  64. return []
  65. }
  66. }
  67. },
  68. data() {
  69. return {
  70. area_picker_show: '',
  71. list: null,
  72. multiIndex: [],
  73. multiArray: [],
  74. place: '',
  75. }
  76. },
  77. created: function () {
  78. this.ids = this.ids.concat();
  79. },
  80. watch: {
  81. ids: function (newData, oldData) {
  82. const self = this;
  83. self.before((data) => {
  84. self.init(data);
  85. })
  86. }
  87. },
  88. methods: {
  89. //#ifdef MP-ALIPAY || MP-TOUTIAO
  90. showAreaPicker: function () {
  91. this.area_picker_show = 'active';
  92. },
  93. hideAreaPicker: function () {
  94. this.area_picker_show = '';
  95. },
  96. areaPickerConfirm: function (e) {
  97. this.bindMultiPickerChange({detail: {value: this.multiIndex}});
  98. this.hideAreaPicker();
  99. },
  100. areaPickerChange: function (e) {
  101. const self = this;
  102. if (self.area_picker_show == '') return;
  103. let detail = {
  104. column: '',
  105. value: '',
  106. };
  107. for (let i = 0; i < 3; i++) {
  108. if (e.detail.value[i] !== self.multiIndex[i]) {
  109. detail.column = i;
  110. detail.value = e.detail.value[i];
  111. break;
  112. }
  113. }
  114. self.multiIndex = e.detail.value;
  115. self.bindMultiPickerColumnChange({detail: detail});
  116. },
  117. //#endif
  118. before(cb) {
  119. const self = this;
  120. const district = uni.getStorageSync("_DISTRICT");
  121. if (district) {
  122. cb(district);
  123. } else {
  124. this.$request({
  125. url: self.$api.default.district,
  126. }).then(info => {
  127. if (info.code === 0) {
  128. uni.setStorageSync("_DISTRICT", info.data.list);
  129. cb(info.data.list);
  130. }
  131. })
  132. }
  133. },
  134. init: function (list) {
  135. const null_status = this.ids.length === 3 && this.ids[0] != 0;
  136. const ids = null_status ? this.ids : [2, 3, 4];
  137. const multiIndex = this.getIndex(list, ids);
  138. const multiArray = [
  139. list,
  140. list[multiIndex[0]].list,
  141. list[multiIndex[0]].list[multiIndex[1]].list
  142. ];
  143. let place = multiArray[0][multiIndex[0]].name
  144. + ','
  145. + multiArray[1][multiIndex[1]].name
  146. + ','
  147. + multiArray[2][multiIndex[2]].name;
  148. /////初始化
  149. let eve = [
  150. multiArray[0][multiIndex[0]],
  151. multiArray[1][multiIndex[1]],
  152. multiArray[2][multiIndex[2]],
  153. ];
  154. ////
  155. this.setEvent(eve, null_status);
  156. [this.list, this.multiArray, this.multiIndex, this.place] = [list, multiArray, multiIndex, null_status ? place : '请选择']
  157. },
  158. getIndex: function (list, data) {
  159. let arr = [];
  160. list.map((item, index) => {
  161. if (data[0] == item.id) arr.push(index)
  162. });
  163. list[arr[0]].list.map((item, index) => {
  164. if (data[1] == item.id) arr.push(index)
  165. });
  166. list[arr[0]].list[arr[1]].list.map((item, index) => {
  167. if (data[2] == item.id) arr.push(index);
  168. });
  169. return arr;
  170. },
  171. bindMultiPickerChange: function (e) {
  172. let list = [
  173. this.multiArray[0][e.detail.value[0]],
  174. this.multiArray[1][e.detail.value[1]],
  175. this.multiArray[2][e.detail.value[2]],
  176. ];
  177. let place = list[0].name
  178. + ','
  179. + list[1].name
  180. + ','
  181. + list[2].name;
  182. [this.multiIndex, this.place] = [e.detail.value, place];
  183. this.setEvent(list);
  184. },
  185. setEvent: function (list, status = true) {
  186. let data = {
  187. province: {
  188. id: list[0].id,
  189. name: list[0].name
  190. },
  191. city: {
  192. id: list[1].id,
  193. name: list[1].name
  194. },
  195. district: {
  196. id: list[2].id,
  197. name: list[2].name
  198. },
  199. };
  200. this.$emit('customevent', status ? data : null);
  201. },
  202. bindMultiPickerColumnChange: function (e) {
  203. let data = {
  204. multiArray: this.multiArray,
  205. multiIndex: this.multiIndex
  206. };
  207. data.multiIndex[e.detail.column] = e.detail.value;
  208. switch (e.detail.column) {
  209. case 0:
  210. data.multiIndex.splice(1, 1, 0);
  211. data.multiIndex.splice(2, 1, 0);
  212. data.multiArray.splice(1, 1, this.list[data.multiIndex[0]].list);
  213. data.multiArray.splice(2, 1, this.list[data.multiIndex[0]].list[data.multiIndex[1]].list);
  214. break;
  215. case 1:
  216. data.multiIndex.splice(2, 1, 0);
  217. data.multiArray.splice(2, 1, this.list[data.multiIndex[0]].list[data.multiIndex[1]].list);
  218. break;
  219. }
  220. [this.multiArray, this.multiIndex] = [data.multiArray, data.multiIndex]
  221. },
  222. },
  223. }
  224. </script>
  225. <style scoped lang="scss">
  226. .area-picker-left {
  227. min-width: #{115rpx};
  228. font-size: #{28rpx};
  229. padding-right: #{24rpx};
  230. line-height: 1.5;
  231. margin-left: auto;
  232. .address-name-color {
  233. color: #353535;
  234. }
  235. .address-place-name-color {
  236. color: #999999;
  237. }
  238. }
  239. .arrow-image {
  240. width: #{12rpx};
  241. height: #{24rpx};
  242. }
  243. /* #ifdef MP-ALIPAY || MP-TOUTIAO */
  244. .area-picker {
  245. position: fixed;
  246. z-index: 1600;
  247. left: 0;
  248. top: 0;
  249. width: 100%;
  250. height: 100%;
  251. display: flex;
  252. flex-direction: column;
  253. transform: translateY(100%);
  254. transition: 250ms opacity;
  255. opacity: 0;
  256. background: rgba(0, 0, 0, .3);
  257. }
  258. .area-picker.active {
  259. transform: translateY(0);
  260. opacity: 1;
  261. }
  262. .area-picker .area-picker-bg {
  263. flex-grow: 1;
  264. position: relative;
  265. }
  266. .area-picker .area-picker-bg > scroll-view {
  267. left: 0;
  268. top: 0;
  269. height: 100%;
  270. width: 100%;
  271. position: absolute;
  272. }
  273. .area-picker .area-picker-body {
  274. flex-grow: 0;
  275. height: #{600rpx};
  276. background: #fff;
  277. transform: translateY(100%);
  278. transition: 250ms transform;
  279. position: relative;
  280. }
  281. .area-picker.active .area-picker-body {
  282. transform: translateY(0);
  283. }
  284. .area-picker .area-picker-body > scroll-view {
  285. left: 0;
  286. top: 0;
  287. height: 100%;
  288. width: 100%;
  289. position: absolute;
  290. }
  291. .area-picker .area-picker-cancel,
  292. .area-picker .area-picker-confirm {
  293. display: inline-block;
  294. padding: #{24rpx};
  295. color: #888;
  296. }
  297. .area-picker .area-picker-confirm {
  298. float: right;
  299. color: #00aa00;
  300. }
  301. .area-picker .area-picker-row {
  302. width: 100%;
  303. height: #{500rpx};
  304. }
  305. /* #endif */
  306. </style>