index.vue 7.9 KB

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