index.vue 7.0 KB

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