295 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			295 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { ref, watch, computed, nextTick, reactive, defineComponent, createVNode as _createVNode, vShow as _vShow, withDirectives as _withDirectives } from "vue";
 | 
						|
import { extend, isObject, isMobile, truthProp, numericProp, makeArrayProp, makeNumericProp, createNamespace } from "../utils/index.mjs";
 | 
						|
import { useExpose } from "../composables/use-expose.mjs";
 | 
						|
import { Area } from "../area/index.mjs";
 | 
						|
import { Cell } from "../cell/index.mjs";
 | 
						|
import { Form } from "../form/index.mjs";
 | 
						|
import { Field } from "../field/index.mjs";
 | 
						|
import { Popup } from "../popup/index.mjs";
 | 
						|
import { showToast } from "../toast/index.mjs";
 | 
						|
import { Button } from "../button/index.mjs";
 | 
						|
import { Switch } from "../switch/index.mjs";
 | 
						|
import AddressEditDetail from "./AddressEditDetail.mjs";
 | 
						|
import { AREA_EMPTY_CODE } from "../area/utils.mjs";
 | 
						|
const [name, bem, t] = createNamespace("address-edit");
 | 
						|
const DEFAULT_DATA = {
 | 
						|
  name: "",
 | 
						|
  tel: "",
 | 
						|
  city: "",
 | 
						|
  county: "",
 | 
						|
  province: "",
 | 
						|
  areaCode: "",
 | 
						|
  isDefault: false,
 | 
						|
  addressDetail: ""
 | 
						|
};
 | 
						|
const addressEditProps = {
 | 
						|
  areaList: Object,
 | 
						|
  isSaving: Boolean,
 | 
						|
  isDeleting: Boolean,
 | 
						|
  validator: Function,
 | 
						|
  showArea: truthProp,
 | 
						|
  showDetail: truthProp,
 | 
						|
  showDelete: Boolean,
 | 
						|
  disableArea: Boolean,
 | 
						|
  searchResult: Array,
 | 
						|
  telMaxlength: numericProp,
 | 
						|
  showSetDefault: Boolean,
 | 
						|
  saveButtonText: String,
 | 
						|
  areaPlaceholder: String,
 | 
						|
  deleteButtonText: String,
 | 
						|
  showSearchResult: Boolean,
 | 
						|
  detailRows: makeNumericProp(1),
 | 
						|
  detailMaxlength: makeNumericProp(200),
 | 
						|
  areaColumnsPlaceholder: makeArrayProp(),
 | 
						|
  addressInfo: {
 | 
						|
    type: Object,
 | 
						|
    default: () => extend({}, DEFAULT_DATA)
 | 
						|
  },
 | 
						|
  telValidator: {
 | 
						|
    type: Function,
 | 
						|
    default: isMobile
 | 
						|
  }
 | 
						|
};
 | 
						|
var stdin_default = defineComponent({
 | 
						|
  name,
 | 
						|
  props: addressEditProps,
 | 
						|
  emits: ["save", "focus", "change", "delete", "clickArea", "changeArea", "changeDetail", "selectSearch", "changeDefault"],
 | 
						|
  setup(props, {
 | 
						|
    emit,
 | 
						|
    slots
 | 
						|
  }) {
 | 
						|
    const areaRef = ref();
 | 
						|
    const data = reactive({});
 | 
						|
    const showAreaPopup = ref(false);
 | 
						|
    const detailFocused = ref(false);
 | 
						|
    const areaListLoaded = computed(() => isObject(props.areaList) && Object.keys(props.areaList).length);
 | 
						|
    const areaText = computed(() => {
 | 
						|
      const {
 | 
						|
        province,
 | 
						|
        city,
 | 
						|
        county,
 | 
						|
        areaCode
 | 
						|
      } = data;
 | 
						|
      if (areaCode) {
 | 
						|
        const arr = [province, city, county];
 | 
						|
        if (province && province === city) {
 | 
						|
          arr.splice(1, 1);
 | 
						|
        }
 | 
						|
        return arr.filter(Boolean).join("/");
 | 
						|
      }
 | 
						|
      return "";
 | 
						|
    });
 | 
						|
    const hideBottomFields = computed(() => {
 | 
						|
      var _a;
 | 
						|
      return ((_a = props.searchResult) == null ? void 0 : _a.length) && detailFocused.value;
 | 
						|
    });
 | 
						|
    const onFocus = (key) => {
 | 
						|
      detailFocused.value = key === "addressDetail";
 | 
						|
      emit("focus", key);
 | 
						|
    };
 | 
						|
    const onChange = (key, value) => {
 | 
						|
      emit("change", {
 | 
						|
        key,
 | 
						|
        value
 | 
						|
      });
 | 
						|
    };
 | 
						|
    const rules = computed(() => {
 | 
						|
      const {
 | 
						|
        validator,
 | 
						|
        telValidator
 | 
						|
      } = props;
 | 
						|
      const makeRule = (name2, emptyMessage) => ({
 | 
						|
        validator: (value) => {
 | 
						|
          if (validator) {
 | 
						|
            const message = validator(name2, value);
 | 
						|
            if (message) {
 | 
						|
              return message;
 | 
						|
            }
 | 
						|
          }
 | 
						|
          if (!value) {
 | 
						|
            return emptyMessage;
 | 
						|
          }
 | 
						|
          return true;
 | 
						|
        }
 | 
						|
      });
 | 
						|
      return {
 | 
						|
        name: [makeRule("name", t("nameEmpty"))],
 | 
						|
        tel: [makeRule("tel", t("telInvalid")), {
 | 
						|
          validator: telValidator,
 | 
						|
          message: t("telInvalid")
 | 
						|
        }],
 | 
						|
        areaCode: [makeRule("areaCode", t("areaEmpty"))],
 | 
						|
        addressDetail: [makeRule("addressDetail", t("addressEmpty"))]
 | 
						|
      };
 | 
						|
    });
 | 
						|
    const onSave = () => emit("save", data);
 | 
						|
    const onChangeDetail = (val) => {
 | 
						|
      data.addressDetail = val;
 | 
						|
      emit("changeDetail", val);
 | 
						|
    };
 | 
						|
    const assignAreaText = (options) => {
 | 
						|
      data.province = options[0].text;
 | 
						|
      data.city = options[1].text;
 | 
						|
      data.county = options[2].text;
 | 
						|
    };
 | 
						|
    const onAreaConfirm = ({
 | 
						|
      selectedValues,
 | 
						|
      selectedOptions
 | 
						|
    }) => {
 | 
						|
      if (selectedValues.some((value) => value === AREA_EMPTY_CODE)) {
 | 
						|
        showToast(t("areaEmpty"));
 | 
						|
      } else {
 | 
						|
        showAreaPopup.value = false;
 | 
						|
        assignAreaText(selectedOptions);
 | 
						|
        emit("changeArea", selectedOptions);
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const onDelete = () => emit("delete", data);
 | 
						|
    const setAreaCode = (code) => {
 | 
						|
      data.areaCode = code || "";
 | 
						|
    };
 | 
						|
    const onDetailBlur = () => {
 | 
						|
      setTimeout(() => {
 | 
						|
        detailFocused.value = false;
 | 
						|
      });
 | 
						|
    };
 | 
						|
    const setAddressDetail = (value) => {
 | 
						|
      data.addressDetail = value;
 | 
						|
    };
 | 
						|
    const renderSetDefaultCell = () => {
 | 
						|
      if (props.showSetDefault) {
 | 
						|
        const slots2 = {
 | 
						|
          "right-icon": () => _createVNode(Switch, {
 | 
						|
            "modelValue": data.isDefault,
 | 
						|
            "onUpdate:modelValue": ($event) => data.isDefault = $event,
 | 
						|
            "onChange": (event) => emit("changeDefault", event)
 | 
						|
          }, null)
 | 
						|
        };
 | 
						|
        return _withDirectives(_createVNode(Cell, {
 | 
						|
          "center": true,
 | 
						|
          "border": false,
 | 
						|
          "title": t("defaultAddress"),
 | 
						|
          "class": bem("default")
 | 
						|
        }, slots2), [[_vShow, !hideBottomFields.value]]);
 | 
						|
      }
 | 
						|
    };
 | 
						|
    useExpose({
 | 
						|
      setAreaCode,
 | 
						|
      setAddressDetail
 | 
						|
    });
 | 
						|
    watch(() => props.addressInfo, (value) => {
 | 
						|
      extend(data, DEFAULT_DATA, value);
 | 
						|
      nextTick(() => {
 | 
						|
        var _a;
 | 
						|
        const options = (_a = areaRef.value) == null ? void 0 : _a.getSelectedOptions();
 | 
						|
        if (options && options.every((option) => option && option.value !== AREA_EMPTY_CODE)) {
 | 
						|
          assignAreaText(options);
 | 
						|
        }
 | 
						|
      });
 | 
						|
    }, {
 | 
						|
      deep: true,
 | 
						|
      immediate: true
 | 
						|
    });
 | 
						|
    return () => {
 | 
						|
      const {
 | 
						|
        disableArea
 | 
						|
      } = props;
 | 
						|
      return _createVNode(Form, {
 | 
						|
        "class": bem(),
 | 
						|
        "onSubmit": onSave
 | 
						|
      }, {
 | 
						|
        default: () => {
 | 
						|
          var _a;
 | 
						|
          return [_createVNode("div", {
 | 
						|
            "class": bem("fields")
 | 
						|
          }, [_createVNode(Field, {
 | 
						|
            "modelValue": data.name,
 | 
						|
            "onUpdate:modelValue": [($event) => data.name = $event, (val) => onChange("name", val)],
 | 
						|
            "clearable": true,
 | 
						|
            "label": t("name"),
 | 
						|
            "rules": rules.value.name,
 | 
						|
            "placeholder": t("name"),
 | 
						|
            "onFocus": () => onFocus("name")
 | 
						|
          }, null), _createVNode(Field, {
 | 
						|
            "modelValue": data.tel,
 | 
						|
            "onUpdate:modelValue": [($event) => data.tel = $event, (val) => onChange("tel", val)],
 | 
						|
            "clearable": true,
 | 
						|
            "type": "tel",
 | 
						|
            "label": t("tel"),
 | 
						|
            "rules": rules.value.tel,
 | 
						|
            "maxlength": props.telMaxlength,
 | 
						|
            "placeholder": t("tel"),
 | 
						|
            "onFocus": () => onFocus("tel")
 | 
						|
          }, null), _withDirectives(_createVNode(Field, {
 | 
						|
            "readonly": true,
 | 
						|
            "label": t("area"),
 | 
						|
            "is-link": !disableArea,
 | 
						|
            "modelValue": areaText.value,
 | 
						|
            "rules": props.showArea ? rules.value.areaCode : void 0,
 | 
						|
            "placeholder": props.areaPlaceholder || t("area"),
 | 
						|
            "onFocus": () => onFocus("areaCode"),
 | 
						|
            "onClick": () => {
 | 
						|
              emit("clickArea");
 | 
						|
              showAreaPopup.value = !disableArea;
 | 
						|
            }
 | 
						|
          }, null), [[_vShow, props.showArea]]), _createVNode(AddressEditDetail, {
 | 
						|
            "show": props.showDetail,
 | 
						|
            "rows": props.detailRows,
 | 
						|
            "rules": rules.value.addressDetail,
 | 
						|
            "value": data.addressDetail,
 | 
						|
            "focused": detailFocused.value,
 | 
						|
            "maxlength": props.detailMaxlength,
 | 
						|
            "searchResult": props.searchResult,
 | 
						|
            "showSearchResult": props.showSearchResult,
 | 
						|
            "onBlur": onDetailBlur,
 | 
						|
            "onFocus": () => onFocus("addressDetail"),
 | 
						|
            "onInput": onChangeDetail,
 | 
						|
            "onSelectSearch": (event) => emit("selectSearch", event)
 | 
						|
          }, null), (_a = slots.default) == null ? void 0 : _a.call(slots)]), renderSetDefaultCell(), _withDirectives(_createVNode("div", {
 | 
						|
            "class": bem("buttons")
 | 
						|
          }, [_createVNode(Button, {
 | 
						|
            "block": true,
 | 
						|
            "round": true,
 | 
						|
            "type": "primary",
 | 
						|
            "text": props.saveButtonText || t("save"),
 | 
						|
            "class": bem("button"),
 | 
						|
            "loading": props.isSaving,
 | 
						|
            "nativeType": "submit"
 | 
						|
          }, null), props.showDelete && _createVNode(Button, {
 | 
						|
            "block": true,
 | 
						|
            "round": true,
 | 
						|
            "class": bem("button"),
 | 
						|
            "loading": props.isDeleting,
 | 
						|
            "text": props.deleteButtonText || t("delete"),
 | 
						|
            "onClick": onDelete
 | 
						|
          }, null)]), [[_vShow, !hideBottomFields.value]]), _createVNode(Popup, {
 | 
						|
            "show": showAreaPopup.value,
 | 
						|
            "onUpdate:show": ($event) => showAreaPopup.value = $event,
 | 
						|
            "round": true,
 | 
						|
            "teleport": "body",
 | 
						|
            "position": "bottom",
 | 
						|
            "lazyRender": false
 | 
						|
          }, {
 | 
						|
            default: () => [_createVNode(Area, {
 | 
						|
              "modelValue": data.areaCode,
 | 
						|
              "onUpdate:modelValue": ($event) => data.areaCode = $event,
 | 
						|
              "ref": areaRef,
 | 
						|
              "loading": !areaListLoaded.value,
 | 
						|
              "areaList": props.areaList,
 | 
						|
              "columnsPlaceholder": props.areaColumnsPlaceholder,
 | 
						|
              "onConfirm": onAreaConfirm,
 | 
						|
              "onCancel": () => {
 | 
						|
                showAreaPopup.value = false;
 | 
						|
              }
 | 
						|
            }, null)]
 | 
						|
          })];
 | 
						|
        }
 | 
						|
      });
 | 
						|
    };
 | 
						|
  }
 | 
						|
});
 | 
						|
export {
 | 
						|
  addressEditProps,
 | 
						|
  stdin_default as default
 | 
						|
};
 |