index.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. // Utils
  3. import { createNamespace, isObject } from '../utils';
  4. import { isMobile } from '../utils/validate/mobile'; // Components
  5. import Area from '../area';
  6. import Cell from '../cell';
  7. import Field from '../field';
  8. import Popup from '../popup';
  9. import Toast from '../toast';
  10. import Button from '../button';
  11. import Dialog from '../dialog';
  12. import Detail from './Detail';
  13. import Switch from '../switch';
  14. var _createNamespace = createNamespace('address-edit'),
  15. createComponent = _createNamespace[0],
  16. bem = _createNamespace[1],
  17. t = _createNamespace[2];
  18. var defaultData = {
  19. name: '',
  20. tel: '',
  21. country: '',
  22. province: '',
  23. city: '',
  24. county: '',
  25. areaCode: '',
  26. postalCode: '',
  27. addressDetail: '',
  28. isDefault: false
  29. };
  30. function isPostal(value) {
  31. return /^\d{6}$/.test(value);
  32. }
  33. export default createComponent({
  34. props: {
  35. areaList: Object,
  36. isSaving: Boolean,
  37. isDeleting: Boolean,
  38. validator: Function,
  39. showDelete: Boolean,
  40. showPostal: Boolean,
  41. searchResult: Array,
  42. telMaxlength: [Number, String],
  43. showSetDefault: Boolean,
  44. saveButtonText: String,
  45. areaPlaceholder: String,
  46. deleteButtonText: String,
  47. showSearchResult: Boolean,
  48. showArea: {
  49. type: Boolean,
  50. default: true
  51. },
  52. showDetail: {
  53. type: Boolean,
  54. default: true
  55. },
  56. disableArea: Boolean,
  57. detailRows: {
  58. type: [Number, String],
  59. default: 1
  60. },
  61. detailMaxlength: {
  62. type: [Number, String],
  63. default: 200
  64. },
  65. addressInfo: {
  66. type: Object,
  67. default: function _default() {
  68. return _extends({}, defaultData);
  69. }
  70. },
  71. telValidator: {
  72. type: Function,
  73. default: isMobile
  74. },
  75. postalValidator: {
  76. type: Function,
  77. default: isPostal
  78. },
  79. areaColumnsPlaceholder: {
  80. type: Array,
  81. default: function _default() {
  82. return [];
  83. }
  84. }
  85. },
  86. data: function data() {
  87. return {
  88. data: {},
  89. showAreaPopup: false,
  90. detailFocused: false,
  91. errorInfo: {
  92. tel: '',
  93. name: '',
  94. areaCode: '',
  95. postalCode: '',
  96. addressDetail: ''
  97. }
  98. };
  99. },
  100. computed: {
  101. areaListLoaded: function areaListLoaded() {
  102. return isObject(this.areaList) && Object.keys(this.areaList).length;
  103. },
  104. areaText: function areaText() {
  105. var _this$data = this.data,
  106. country = _this$data.country,
  107. province = _this$data.province,
  108. city = _this$data.city,
  109. county = _this$data.county,
  110. areaCode = _this$data.areaCode;
  111. if (areaCode) {
  112. var arr = [country, province, city, county];
  113. if (province && province === city) {
  114. arr.splice(1, 1);
  115. }
  116. return arr.filter(function (text) {
  117. return text;
  118. }).join('/');
  119. }
  120. return '';
  121. },
  122. // hide bottom field when use search && detail get focused
  123. hideBottomFields: function hideBottomFields() {
  124. var searchResult = this.searchResult;
  125. return searchResult && searchResult.length && this.detailFocused;
  126. }
  127. },
  128. watch: {
  129. addressInfo: {
  130. handler: function handler(val) {
  131. this.data = _extends({}, defaultData, val);
  132. this.setAreaCode(val.areaCode);
  133. },
  134. deep: true,
  135. immediate: true
  136. },
  137. areaList: function areaList() {
  138. this.setAreaCode(this.data.areaCode);
  139. }
  140. },
  141. methods: {
  142. onFocus: function onFocus(key) {
  143. this.errorInfo[key] = '';
  144. this.detailFocused = key === 'addressDetail';
  145. this.$emit('focus', key);
  146. },
  147. onChangeDetail: function onChangeDetail(val) {
  148. this.data.addressDetail = val;
  149. this.$emit('change-detail', val);
  150. },
  151. onAreaConfirm: function onAreaConfirm(values) {
  152. values = values.filter(function (value) {
  153. return !!value;
  154. });
  155. if (values.some(function (value) {
  156. return !value.code;
  157. })) {
  158. Toast(t('areaEmpty'));
  159. return;
  160. }
  161. this.showAreaPopup = false;
  162. this.assignAreaValues();
  163. this.$emit('change-area', values);
  164. },
  165. assignAreaValues: function assignAreaValues() {
  166. var area = this.$refs.area;
  167. if (area) {
  168. var detail = area.getArea();
  169. detail.areaCode = detail.code;
  170. delete detail.code;
  171. _extends(this.data, detail);
  172. }
  173. },
  174. onSave: function onSave() {
  175. var _this = this;
  176. var items = ['name', 'tel'];
  177. if (this.showArea) {
  178. items.push('areaCode');
  179. }
  180. if (this.showDetail) {
  181. items.push('addressDetail');
  182. }
  183. if (this.showPostal) {
  184. items.push('postalCode');
  185. }
  186. var isValid = items.every(function (item) {
  187. var msg = _this.getErrorMessage(item);
  188. if (msg) {
  189. _this.errorInfo[item] = msg;
  190. }
  191. return !msg;
  192. });
  193. if (isValid && !this.isSaving) {
  194. this.$emit('save', this.data);
  195. }
  196. },
  197. getErrorMessage: function getErrorMessage(key) {
  198. var value = String(this.data[key] || '').trim();
  199. if (this.validator) {
  200. var message = this.validator(key, value);
  201. if (message) {
  202. return message;
  203. }
  204. }
  205. switch (key) {
  206. case 'name':
  207. return value ? '' : t('nameEmpty');
  208. case 'tel':
  209. return this.telValidator(value) ? '' : t('telInvalid');
  210. case 'areaCode':
  211. return value ? '' : t('areaEmpty');
  212. case 'addressDetail':
  213. return value ? '' : t('addressEmpty');
  214. case 'postalCode':
  215. return value && !this.postalValidator(value) ? t('postalEmpty') : '';
  216. }
  217. },
  218. onDelete: function onDelete() {
  219. var _this2 = this;
  220. Dialog.confirm({
  221. title: t('confirmDelete')
  222. }).then(function () {
  223. _this2.$emit('delete', _this2.data);
  224. }).catch(function () {
  225. _this2.$emit('cancel-delete', _this2.data);
  226. });
  227. },
  228. // get values of area component
  229. getArea: function getArea() {
  230. return this.$refs.area ? this.$refs.area.getValues() : [];
  231. },
  232. // set area code to area component
  233. setAreaCode: function setAreaCode(code) {
  234. this.data.areaCode = code || '';
  235. if (code) {
  236. this.$nextTick(this.assignAreaValues);
  237. }
  238. },
  239. // @exposed-api
  240. setAddressDetail: function setAddressDetail(value) {
  241. this.data.addressDetail = value;
  242. },
  243. onDetailBlur: function onDetailBlur() {
  244. var _this3 = this;
  245. // await for click search event
  246. setTimeout(function () {
  247. _this3.detailFocused = false;
  248. });
  249. },
  250. genSetDefaultCell: function genSetDefaultCell(h) {
  251. var _this4 = this;
  252. if (this.showSetDefault) {
  253. var slots = {
  254. 'right-icon': function rightIcon() {
  255. return h(Switch, {
  256. "attrs": {
  257. "size": "24"
  258. },
  259. "on": {
  260. "change": function change(event) {
  261. _this4.$emit('change-default', event);
  262. }
  263. },
  264. "model": {
  265. value: _this4.data.isDefault,
  266. callback: function callback($$v) {
  267. _this4.$set(_this4.data, "isDefault", $$v);
  268. }
  269. }
  270. });
  271. }
  272. };
  273. return h(Cell, {
  274. "directives": [{
  275. name: "show",
  276. value: !this.hideBottomFields
  277. }],
  278. "attrs": {
  279. "center": true,
  280. "title": t('defaultAddress')
  281. },
  282. "class": bem('default'),
  283. "scopedSlots": slots
  284. });
  285. }
  286. return h();
  287. }
  288. },
  289. render: function render(h) {
  290. var _this5 = this;
  291. var data = this.data,
  292. errorInfo = this.errorInfo,
  293. disableArea = this.disableArea,
  294. hideBottomFields = this.hideBottomFields;
  295. var onFocus = function onFocus(name) {
  296. return function () {
  297. return _this5.onFocus(name);
  298. };
  299. };
  300. return h("div", {
  301. "class": bem()
  302. }, [h("div", {
  303. "class": bem('fields')
  304. }, [h(Field, {
  305. "attrs": {
  306. "clearable": true,
  307. "label": t('name'),
  308. "placeholder": t('namePlaceholder'),
  309. "errorMessage": errorInfo.name
  310. },
  311. "on": {
  312. "focus": onFocus('name')
  313. },
  314. "model": {
  315. value: data.name,
  316. callback: function callback($$v) {
  317. _this5.$set(data, "name", $$v);
  318. }
  319. }
  320. }), h(Field, {
  321. "attrs": {
  322. "clearable": true,
  323. "type": "tel",
  324. "label": t('tel'),
  325. "maxlength": this.telMaxlength,
  326. "placeholder": t('telPlaceholder'),
  327. "errorMessage": errorInfo.tel
  328. },
  329. "on": {
  330. "focus": onFocus('tel')
  331. },
  332. "model": {
  333. value: data.tel,
  334. callback: function callback($$v) {
  335. _this5.$set(data, "tel", $$v);
  336. }
  337. }
  338. }), h(Field, {
  339. "directives": [{
  340. name: "show",
  341. value: this.showArea
  342. }],
  343. "attrs": {
  344. "readonly": true,
  345. "clickable": !disableArea,
  346. "label": t('area'),
  347. "placeholder": this.areaPlaceholder || t('areaPlaceholder'),
  348. "errorMessage": errorInfo.areaCode,
  349. "rightIcon": !disableArea ? 'arrow' : null,
  350. "value": this.areaText
  351. },
  352. "on": {
  353. "focus": onFocus('areaCode'),
  354. "click": function click() {
  355. _this5.$emit('click-area');
  356. _this5.showAreaPopup = !disableArea;
  357. }
  358. }
  359. }), h(Detail, {
  360. "directives": [{
  361. name: "show",
  362. value: this.showDetail
  363. }],
  364. "attrs": {
  365. "focused": this.detailFocused,
  366. "value": data.addressDetail,
  367. "errorMessage": errorInfo.addressDetail,
  368. "detailRows": this.detailRows,
  369. "detailMaxlength": this.detailMaxlength,
  370. "searchResult": this.searchResult,
  371. "showSearchResult": this.showSearchResult
  372. },
  373. "on": {
  374. "focus": onFocus('addressDetail'),
  375. "blur": this.onDetailBlur,
  376. "input": this.onChangeDetail,
  377. "select-search": function selectSearch(event) {
  378. _this5.$emit('select-search', event);
  379. }
  380. }
  381. }), this.showPostal && h(Field, {
  382. "directives": [{
  383. name: "show",
  384. value: !hideBottomFields
  385. }],
  386. "attrs": {
  387. "type": "tel",
  388. "maxlength": "6",
  389. "label": t('postal'),
  390. "placeholder": t('postal'),
  391. "errorMessage": errorInfo.postalCode
  392. },
  393. "on": {
  394. "focus": onFocus('postalCode')
  395. },
  396. "model": {
  397. value: data.postalCode,
  398. callback: function callback($$v) {
  399. _this5.$set(data, "postalCode", $$v);
  400. }
  401. }
  402. }), this.slots()]), this.genSetDefaultCell(h), h("div", {
  403. "directives": [{
  404. name: "show",
  405. value: !hideBottomFields
  406. }],
  407. "class": bem('buttons')
  408. }, [h(Button, {
  409. "attrs": {
  410. "block": true,
  411. "round": true,
  412. "loading": this.isSaving,
  413. "type": "danger",
  414. "text": this.saveButtonText || t('save')
  415. },
  416. "on": {
  417. "click": this.onSave
  418. }
  419. }), this.showDelete && h(Button, {
  420. "attrs": {
  421. "block": true,
  422. "round": true,
  423. "loading": this.isDeleting,
  424. "text": this.deleteButtonText || t('delete')
  425. },
  426. "on": {
  427. "click": this.onDelete
  428. }
  429. })]), h(Popup, {
  430. "attrs": {
  431. "round": true,
  432. "position": "bottom",
  433. "lazyRender": false,
  434. "getContainer": "body"
  435. },
  436. "model": {
  437. value: _this5.showAreaPopup,
  438. callback: function callback($$v) {
  439. _this5.showAreaPopup = $$v;
  440. }
  441. }
  442. }, [h(Area, {
  443. "ref": "area",
  444. "attrs": {
  445. "value": data.areaCode,
  446. "loading": !this.areaListLoaded,
  447. "areaList": this.areaList,
  448. "columnsPlaceholder": this.areaColumnsPlaceholder
  449. },
  450. "on": {
  451. "confirm": this.onAreaConfirm,
  452. "cancel": function cancel() {
  453. _this5.showAreaPopup = false;
  454. }
  455. }
  456. })])]);
  457. }
  458. });