| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335 |
- import { use, isObj } from '../utils';
- import { isMobile } from '../utils/validate/mobile';
- import Area from '../area';
- import Field from '../field';
- import Popup from '../popup';
- import Toast from '../toast';
- import Button from '../button';
- import Dialog from '../dialog';
- import Detail from './Detail';
- import SwitchCell from '../switch-cell';
- const [sfc, bem, t] = use('address-edit');
- const defaultData = {
- name: '',
- tel: '',
- country: '',
- province: '',
- city: '',
- county: '',
- areaCode: '',
- postalCode: '',
- addressDetail: '',
- isDefault: false
- };
- export default sfc({
- props: {
- areaList: Object,
- isSaving: Boolean,
- isDeleting: Boolean,
- validator: Function,
- showDelete: Boolean,
- showPostal: Boolean,
- searchResult: Array,
- showSetDefault: Boolean,
- showSearchResult: Boolean,
- saveButtonText: String,
- deleteButtonText: String,
- showArea: {
- type: Boolean,
- default: true
- },
- showDetail: {
- type: Boolean,
- default: true
- },
- detailRows: {
- type: Number,
- default: 1
- },
- addressInfo: {
- type: Object,
- default: () => ({ ...defaultData })
- },
- telValidator: {
- type: Function,
- default: isMobile
- }
- },
- data() {
- return {
- data: {},
- showAreaPopup: false,
- detailFocused: false,
- errorInfo: {
- tel: false,
- name: false,
- postalCode: false,
- addressDetail: false
- }
- };
- },
- computed: {
- areaListLoaded() {
- return isObj(this.areaList) && Object.keys(this.areaList).length;
- },
- areaText() {
- const { country, province, city, county, areaCode } = this.data;
- if (areaCode) {
- const arr = [country, province, city, county];
- if (province && province === city) {
- arr.splice(1, 1);
- }
- return arr.filter(text => text).join('/');
- }
- return '';
- }
- },
- watch: {
- addressInfo: {
- handler(val) {
- this.data = {
- ...defaultData,
- ...val
- };
- this.setAreaCode(val.areaCode);
- },
- deep: true,
- immediate: true
- },
- areaList() {
- this.setAreaCode(this.data.areaCode);
- }
- },
- methods: {
- onFocus(key) {
- this.errorInfo[key] = false;
- this.detailFocused = key === 'addressDetail';
- this.$emit('focus', key);
- },
- onChangeDetail(val) {
- this.data.addressDetail = val;
- this.$emit('change-detail', val);
- },
- onAreaConfirm(values) {
- this.showAreaPopup = false;
- this.assignAreaValues();
- this.$emit('change-area', values);
- },
- assignAreaValues() {
- const { area } = this.$refs;
- if (area) {
- const detail = area.getArea();
- detail.areaCode = detail.code;
- delete detail.code;
- Object.assign(this.data, detail);
- }
- },
- onSave() {
- const items = ['name', 'tel', 'areaCode', 'addressDetail'];
- if (this.showPostal) {
- items.push('postalCode');
- }
- const isValid = items.every(item => {
- const msg = this.getErrorMessage(item);
- if (msg) {
- this.errorInfo[item] = true;
- Toast(msg);
- }
- return !msg;
- });
- if (isValid && !this.isSaving) {
- this.$emit('save', this.data);
- }
- },
- getErrorMessage(key) {
- const value = String(this.data[key] || '').trim();
- if (this.validator) {
- const message = this.validator(key, value);
- if (message) {
- return message;
- }
- }
- switch (key) {
- case 'name':
- return value ? '' : t('nameEmpty');
- case 'tel':
- return this.telValidator(value) ? '' : t('telInvalid');
- case 'areaCode':
- return value ? '' : t('areaEmpty');
- case 'addressDetail':
- return value ? '' : t('addressEmpty');
- case 'postalCode':
- return value && !/^\d{6}$/.test(value) ? t('postalEmpty') : '';
- }
- },
- onDelete() {
- Dialog.confirm({
- title: t('confirmDelete')
- })
- .then(() => {
- this.$emit('delete', this.data);
- })
- .catch(() => {
- this.$emit('cancel-delete', this.data);
- });
- },
- // get values of area component
- getArea() {
- return this.$refs.area ? this.$refs.area.getValues() : [];
- },
- // set area code to area component
- setAreaCode(code) {
- this.data.areaCode = code || '';
- if (code) {
- this.$nextTick(this.assignAreaValues);
- }
- },
- setAddressDetail(value) {
- this.data.addressDetail = value;
- },
- onDetailBlur() {
- // await for click search event
- setTimeout(() => {
- this.detailFocused = false;
- });
- }
- },
- render(h) {
- const { data, errorInfo } = this;
- const onFocus = name => () => this.onFocus(name);
- // hide bottom field when use search && detail get focused
- const hideBottomFields = this.searchResult.length && this.detailFocused;
- return (
- <div class={bem()}>
- <Field
- vModel={data.name}
- clearable
- label={t('name')}
- placeholder={t('namePlaceholder')}
- error={errorInfo.name}
- onFocus={onFocus('name')}
- />
- <Field
- vModel={data.tel}
- clearable
- type="tel"
- label={t('tel')}
- placeholder={t('telPlaceholder')}
- error={errorInfo.tel}
- onFocus={onFocus('tel')}
- />
- <Field
- vShow={this.showArea}
- readonly
- label={t('area')}
- placeholder={t('areaPlaceholder')}
- value={this.areaText}
- onClick={() => {
- this.showAreaPopup = true;
- }}
- />
- <Detail
- vShow={this.showDetail}
- focused={this.detailFocused}
- value={data.addressDetail}
- error={errorInfo.addressDetail}
- detailRows={this.detailRows}
- searchResult={this.searchResult}
- showSearchResult={this.showSearchResult}
- onFocus={onFocus('addressDetail')}
- onBlur={this.onDetailBlur}
- onInput={this.onChangeDetail}
- onSelect-search={event => {
- this.$emit('select-search', event);
- }}
- />
- {this.showPostal && (
- <Field
- vShow={!hideBottomFields}
- vModel={data.postalCode}
- type="tel"
- maxlength="6"
- label={t('postal')}
- placeholder={t('postal')}
- error={errorInfo.postalCode}
- onFocus={onFocus('postalCode')}
- />
- )}
- {this.slots()}
- {this.showSetDefault && (
- <SwitchCell
- vModel={data.isDefault}
- vShow={!hideBottomFields}
- title={t('defaultAddress')}
- onChange={event => {
- this.$emit('change-default', event);
- }}
- />
- )}
- <div vShow={!hideBottomFields} class={bem('buttons')}>
- <Button
- block
- loading={this.isSaving}
- type="danger"
- text={this.saveButtonText || t('save')}
- onClick={this.onSave}
- />
- {this.showDelete && (
- <Button
- block
- loading={this.isDeleting}
- text={this.deleteButtonText || t('delete')}
- onClick={this.onDelete}
- />
- )}
- </div>
- <Popup
- vModel={this.showAreaPopup}
- position="bottom"
- lazyRender={false}
- getContainer="body"
- >
- <Area
- ref="area"
- loading={!this.areaListLoaded}
- value={data.areaCode}
- areaList={this.areaList}
- onConfirm={this.onAreaConfirm}
- onCancel={() => {
- this.showAreaPopup = false;
- }}
- />
- </Popup>
- </div>
- );
- }
- });
|