index.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. <template>
  2. <uni-shadow-root class="vant-area-index"><van-picker class="van-area__picker" active-class="active-class" toolbar-class="toolbar-class" column-class="column-class" show-toolbar value-key="name" :title="title" :loading="loading" :columns="computed.displayColumns(columns, columnsNum)" :item-height="itemHeight" :visible-item-count="visibleItemCount" :cancel-button-text="cancelButtonText" :confirm-button-text="confirmButtonText" @change="onChange" @confirm="onConfirm" @cancel="onCancel"></van-picker></uni-shadow-root>
  3. </template>
  4. <wxs src="./index.wxs" module="computed"></wxs>
  5. <script>
  6. import VanPicker from '../picker/index.vue'
  7. global['__wxVueOptions'] = {components:{'van-picker': VanPicker}}
  8. global['__wxRoute'] = 'vant/area/index'
  9. import { VantComponent } from '../common/component';
  10. import { pickerProps } from '../picker/shared';
  11. import { requestAnimationFrame } from '../common/utils';
  12. const EMPTY_CODE = '000000';
  13. VantComponent({
  14. classes: ['active-class', 'toolbar-class', 'column-class'],
  15. props: Object.assign(Object.assign({}, pickerProps), {
  16. value: {
  17. type: String,
  18. observer(value) {
  19. this.code = value;
  20. this.setValues();
  21. },
  22. },
  23. areaList: {
  24. type: Object,
  25. value: {},
  26. observer: 'setValues',
  27. },
  28. columnsNum: {
  29. type: null,
  30. value: 3,
  31. },
  32. columnsPlaceholder: {
  33. type: Array,
  34. observer(val) {
  35. this.setData({
  36. typeToColumnsPlaceholder: {
  37. province: val[0] || '',
  38. city: val[1] || '',
  39. county: val[2] || '',
  40. },
  41. });
  42. },
  43. },
  44. }),
  45. data: {
  46. columns: [{ values: [] }, { values: [] }, { values: [] }],
  47. typeToColumnsPlaceholder: {},
  48. },
  49. mounted() {
  50. requestAnimationFrame(() => {
  51. this.setValues();
  52. });
  53. },
  54. methods: {
  55. getPicker() {
  56. if (this.picker == null) {
  57. this.picker = this.selectComponent('.van-area__picker');
  58. }
  59. return this.picker;
  60. },
  61. onCancel(event) {
  62. this.emit('cancel', event.detail);
  63. },
  64. onConfirm(event) {
  65. const { index } = event.detail;
  66. let { value } = event.detail;
  67. value = this.parseValues(value);
  68. this.emit('confirm', { value, index });
  69. },
  70. emit(type, detail) {
  71. detail.values = detail.value;
  72. delete detail.value;
  73. this.$emit(type, detail);
  74. },
  75. parseValues(values) {
  76. const { columnsPlaceholder } = this.data;
  77. return values.map((value, index) => {
  78. if (
  79. value &&
  80. (!value.code || value.name === columnsPlaceholder[index])
  81. ) {
  82. return Object.assign(Object.assign({}, value), {
  83. code: '',
  84. name: '',
  85. });
  86. }
  87. return value;
  88. });
  89. },
  90. onChange(event) {
  91. const { index, picker, value } = event.detail;
  92. this.code = value[index].code;
  93. this.setValues().then(() => {
  94. this.$emit('change', {
  95. picker,
  96. values: this.parseValues(picker.getValues()),
  97. index,
  98. });
  99. });
  100. },
  101. getConfig(type) {
  102. const { areaList } = this.data;
  103. return (areaList && areaList[`${type}_list`]) || {};
  104. },
  105. getList(type, code) {
  106. if (type !== 'province' && !code) {
  107. return [];
  108. }
  109. const { typeToColumnsPlaceholder } = this.data;
  110. const list = this.getConfig(type);
  111. let result = Object.keys(list).map((code) => ({
  112. code,
  113. name: list[code],
  114. }));
  115. if (code != null) {
  116. // oversea code
  117. if (code[0] === '9' && type === 'city') {
  118. code = '9';
  119. }
  120. result = result.filter((item) => item.code.indexOf(code) === 0);
  121. }
  122. if (typeToColumnsPlaceholder[type] && result.length) {
  123. // set columns placeholder
  124. const codeFill =
  125. type === 'province'
  126. ? ''
  127. : type === 'city'
  128. ? EMPTY_CODE.slice(2, 4)
  129. : EMPTY_CODE.slice(4, 6);
  130. result.unshift({
  131. code: `${code}${codeFill}`,
  132. name: typeToColumnsPlaceholder[type],
  133. });
  134. }
  135. return result;
  136. },
  137. getIndex(type, code) {
  138. let compareNum = type === 'province' ? 2 : type === 'city' ? 4 : 6;
  139. const list = this.getList(type, code.slice(0, compareNum - 2));
  140. // oversea code
  141. if (code[0] === '9' && type === 'province') {
  142. compareNum = 1;
  143. }
  144. code = code.slice(0, compareNum);
  145. for (let i = 0; i < list.length; i++) {
  146. if (list[i].code.slice(0, compareNum) === code) {
  147. return i;
  148. }
  149. }
  150. return 0;
  151. },
  152. setValues() {
  153. const picker = this.getPicker();
  154. if (!picker) {
  155. return;
  156. }
  157. let code = this.code || this.getDefaultCode();
  158. const provinceList = this.getList('province');
  159. const cityList = this.getList('city', code.slice(0, 2));
  160. const stack = [];
  161. const indexes = [];
  162. const { columnsNum } = this.data;
  163. if (columnsNum >= 1) {
  164. stack.push(picker.setColumnValues(0, provinceList, false));
  165. indexes.push(this.getIndex('province', code));
  166. }
  167. if (columnsNum >= 2) {
  168. stack.push(picker.setColumnValues(1, cityList, false));
  169. indexes.push(this.getIndex('city', code));
  170. if (cityList.length && code.slice(2, 4) === '00') {
  171. [{ code }] = cityList;
  172. }
  173. }
  174. if (columnsNum === 3) {
  175. stack.push(
  176. picker.setColumnValues(
  177. 2,
  178. this.getList('county', code.slice(0, 4)),
  179. false
  180. )
  181. );
  182. indexes.push(this.getIndex('county', code));
  183. }
  184. return Promise.all(stack)
  185. .catch(() => {})
  186. .then(() => picker.setIndexes(indexes))
  187. .catch(() => {});
  188. },
  189. getDefaultCode() {
  190. const { columnsPlaceholder } = this.data;
  191. if (columnsPlaceholder.length) {
  192. return EMPTY_CODE;
  193. }
  194. const countyCodes = Object.keys(this.getConfig('county'));
  195. if (countyCodes[0]) {
  196. return countyCodes[0];
  197. }
  198. const cityCodes = Object.keys(this.getConfig('city'));
  199. if (cityCodes[0]) {
  200. return cityCodes[0];
  201. }
  202. return '';
  203. },
  204. getValues() {
  205. const picker = this.getPicker();
  206. if (!picker) {
  207. return [];
  208. }
  209. return this.parseValues(picker.getValues().filter((value) => !!value));
  210. },
  211. getDetail() {
  212. const values = this.getValues();
  213. const area = {
  214. code: '',
  215. country: '',
  216. province: '',
  217. city: '',
  218. county: '',
  219. };
  220. if (!values.length) {
  221. return area;
  222. }
  223. const names = values.map((item) => item.name);
  224. area.code = values[values.length - 1].code;
  225. if (area.code[0] === '9') {
  226. area.country = names[1] || '';
  227. area.province = names[2] || '';
  228. } else {
  229. area.province = names[0] || '';
  230. area.city = names[1] || '';
  231. area.county = names[2] || '';
  232. }
  233. return area;
  234. },
  235. reset(code) {
  236. this.code = code || '';
  237. return this.setValues();
  238. },
  239. },
  240. });
  241. export default global['__wxComponents']['vant/area/index']
  242. </script>
  243. <style platform="mp-weixin">
  244. @import '../common/index.css';
  245. </style>