diff --git a/src/address-edit/Detail.js b/src/address-edit/Detail.tsx similarity index 84% rename from src/address-edit/Detail.js rename to src/address-edit/Detail.tsx index 59ae60a15..ed5c431a6 100644 --- a/src/address-edit/Detail.js +++ b/src/address-edit/Detail.tsx @@ -1,4 +1,4 @@ -import { ref } from 'vue'; +import { PropType, ref } from 'vue'; // Utils import { createNamespace } from '../utils'; @@ -11,14 +11,19 @@ import Field from '../field'; const [createComponent, bem, t] = createNamespace('address-edit-detail'); const android = isAndroid(); +export type AddressEditSearchItem = { + name: string; + address: string; +}; + export default createComponent({ props: { show: Boolean, value: String, - errorMessage: String, focused: Boolean, detailRows: [Number, String], - searchResult: Array, + searchResult: Array as PropType, + errorMessage: String, detailMaxlength: [Number, String], showSearchResult: Boolean, }, @@ -31,7 +36,7 @@ export default createComponent({ const showSearchResult = () => props.focused && props.searchResult && props.showSearchResult; - const onSelect = (express) => { + const onSelect = (express: AddressEditSearchItem) => { emit('select-search', express); emit('input', `${express.address || ''} ${express.name || ''}`.trim()); }; @@ -50,10 +55,10 @@ export default createComponent({ } }; - const renderSearchTitle = (express) => { + const renderSearchTitle = (express: AddressEditSearchItem) => { if (express.name) { const text = express.name.replace( - props.value, + props.value!, `${props.value}` ); @@ -67,7 +72,7 @@ export default createComponent({ } const { searchResult } = props; - return searchResult.map((express) => ( + return searchResult!.map((express) => ( renderSearchTitle(express), @@ -85,15 +90,15 @@ export default createComponent({ )); }; - const onFocus = (event) => { + const onFocus = (event: Event) => { emit('focus', event); }; - const onBlur = (event) => { + const onBlur = (event: Event) => { emit('blur', event); }; - const onInput = (value) => { + const onInput = (value: string) => { emit('input', value); }; diff --git a/src/address-edit/README.md b/src/address-edit/README.md index 4fdae133e..025df38d8 100644 --- a/src/address-edit/README.md +++ b/src/address-edit/README.md @@ -122,18 +122,17 @@ Use [ref](https://v3.vuejs.org/guide/component-template-refs.html) to get Addres ### AddressInfo Data Structure -| key | Description | Type | -| ------------- | ------------------ | ------------------ | -| id | Address Id | _number \| string_ | -| name | Name | _string_ | -| tel | Phone | _string_ | -| province | Province | _string_ | -| city | City | _string_ | -| county | County | _string_ | -| addressDetail | Detailed Address | _string_ | -| areaCode | Area code | _string_ | -| postalCode | Postal code | _string_ | -| isDefault | Is default address | _boolean_ | +| key | Description | Type | +| ------------- | ------------------ | --------- | +| name | Name | _string_ | +| tel | Phone | _string_ | +| province | Province | _string_ | +| city | City | _string_ | +| county | County | _string_ | +| addressDetail | Detailed Address | _string_ | +| areaCode | Area code | _string_ | +| postalCode | Postal code | _string_ | +| isDefault | Is default address | _boolean_ | ### SearchResult Data Structure diff --git a/src/address-edit/README.zh-CN.md b/src/address-edit/README.zh-CN.md index e258b82bd..62a4f78a2 100644 --- a/src/address-edit/README.zh-CN.md +++ b/src/address-edit/README.zh-CN.md @@ -126,20 +126,19 @@ export default { ### AddressInfo 数据格式 -注意:AddressInfo 仅作为初始值传入,表单最终内容可以在 save 事件中获取 +注意:`AddressInfo` 仅作为初始值传入,表单最终内容可以在 save 事件中获取。 -| key | 说明 | 类型 | -| ------------- | -------------------------------------- | ------------------ | -| id | 每条地址的唯一标识 | _number \| string_ | -| name | 收货人姓名 | _string_ | -| tel | 收货人手机号 | _string_ | -| province | 省份 | _string_ | -| city | 城市 | _string_ | -| county | 区县 | _string_ | -| addressDetail | 详细地址 | _string_ | -| areaCode | 地区编码,通过`省市区选择`获取(必填) | _string_ | -| postalCode | 邮政编码 | _string_ | -| isDefault | 是否为默认地址 | _boolean_ | +| key | 说明 | 类型 | +| --- | --- | --- | +| name | 收货人姓名 | _string_ | +| tel | 收货人手机号 | _string_ | +| province | 省份 | _string_ | +| city | 城市 | _string_ | +| county | 区县 | _string_ | +| addressDetail | 详细地址 | _string_ | +| areaCode | 地区编码,通过 [省市区选择](#/zh-CN/area) 获取(必填) | _string_ | +| postalCode | 邮政编码 | _string_ | +| isDefault | 是否为默认地址 | _boolean_ | ### SearchResult 数据格式 diff --git a/src/address-edit/index.js b/src/address-edit/index.tsx similarity index 87% rename from src/address-edit/index.js rename to src/address-edit/index.tsx index eaf44cfc9..ab13b3a5a 100644 --- a/src/address-edit/index.js +++ b/src/address-edit/index.tsx @@ -1,4 +1,4 @@ -import { ref, watch, computed, nextTick, reactive } from 'vue'; +import { ref, watch, computed, nextTick, reactive, PropType } from 'vue'; // Utils import { createNamespace, isObject } from '../utils'; @@ -8,45 +8,58 @@ import { isMobile } from '../utils/validate/mobile'; import { useExpose } from '../composables/use-expose'; // Components -import Area from '../area'; +import Area, { AreaList, AreaColumnOption } from '../area'; import Cell from '../cell'; 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 Switch from '../switch'; +import Detail, { AddressEditSearchItem } from './Detail'; const [createComponent, bem, t] = createNamespace('address-edit'); -const defaultData = { - name: '', - tel: '', - country: '', - province: '', - city: '', - county: '', - areaCode: '', - postalCode: '', - addressDetail: '', - isDefault: false, +export type AddressInfo = { + tel: string; + name: string; + city: string; + county: string; + country: string; + province: string; + areaCode: string; + isDefault?: boolean; + postalCode?: string; + addressDetail: string; }; -function isPostal(value) { +const defaultData: AddressInfo = { + name: '', + tel: '', + city: '', + county: '', + country: '', + province: '', + areaCode: '', + isDefault: false, + postalCode: '', + addressDetail: '', +}; + +function isPostal(value: string) { return /^\d{6}$/.test(value); } export default createComponent({ props: { - areaList: Object, + areaList: Object as PropType, isSaving: Boolean, isDeleting: Boolean, validator: Function, showDelete: Boolean, showPostal: Boolean, disableArea: Boolean, - searchResult: Array, + searchResult: Array as PropType, telMaxlength: [Number, String], showSetDefault: Boolean, saveButtonText: String, @@ -70,19 +83,19 @@ export default createComponent({ default: 200, }, addressInfo: { - type: Object, + type: Object as PropType>, default: () => ({ ...defaultData }), }, telValidator: { - type: Function, + type: Function as PropType<(val: string) => boolean>, default: isMobile, }, postalValidator: { - type: Function, + type: Function as PropType<(val: string) => boolean>, default: isPostal, }, areaColumnsPlaceholder: { - type: Array, + type: Array as PropType, default: () => [], }, }, @@ -103,7 +116,7 @@ export default createComponent({ const areaRef = ref(); const state = reactive({ - data: {}, + data: {} as AddressInfo, showAreaPopup: false, detailFocused: false, errorInfo: { @@ -112,7 +125,7 @@ export default createComponent({ areaCode: '', postalCode: '', addressDetail: '', - }, + } as Record, }); const areaListLoaded = computed( @@ -146,14 +159,14 @@ export default createComponent({ } }; - const onFocus = (key) => { + const onFocus = (key: string) => { state.errorInfo[key] = ''; state.detailFocused = key === 'addressDetail'; emit('focus', key); }; - const getErrorMessage = (key) => { - const value = String(state.data[key] || '').trim(); + const getErrorMessage = (key: string) => { + const value = String((state.data as any)[key] || '').trim(); if (props.validator) { const message = props.validator(key, value); @@ -204,12 +217,12 @@ export default createComponent({ } }; - const onChangeDetail = (val) => { + const onChangeDetail = (val: string) => { state.data.addressDetail = val; emit('change-detail', val); }; - const onAreaConfirm = (values) => { + const onAreaConfirm = (values: AreaColumnOption[]) => { values = values.filter((value) => !!value); if (values.some((value) => !value.code)) { @@ -238,7 +251,7 @@ export default createComponent({ const getArea = () => (areaRef.value ? areaRef.value.getValues() : []); // set area code to area component - const setAreaCode = (code) => { + const setAreaCode = (code?: string) => { state.data.areaCode = code || ''; if (code) { @@ -253,7 +266,7 @@ export default createComponent({ }); }; - const setAddressDetail = (value) => { + const setAddressDetail = (value: string) => { state.data.addressDetail = value; }; @@ -262,7 +275,7 @@ export default createComponent({ const slots = { 'right-icon': () => ( { emit('change-default', event); @@ -365,7 +378,7 @@ export default createComponent({ onBlur={onDetailBlur} onFocus={() => onFocus('addressDetail')} onInput={onChangeDetail} - onSelect-search={(event) => { + onSelect-search={(event: Event) => { emit('select-search', event); }} /> @@ -404,7 +417,7 @@ export default createComponent({ )} ; }; +export type AreaColumnOption = { + name: string; + code: string; +}; + type ColumnType = 'province' | 'county' | 'city'; export default createComponent({ @@ -109,7 +114,7 @@ export default createComponent({ }; const getColumnValues = (type: ColumnType, code?: string) => { - let column: PickerObjectOption[] = []; + let column: AreaColumnOption[] = []; if (type !== 'province' && !code) { return column; } @@ -202,7 +207,7 @@ export default createComponent({ }; // parse output columns data - const parseValues = (values: PickerObjectOption[]) => { + const parseValues = (values: AreaColumnOption[]) => { return values.map((value, index) => { if (value) { value = deepClone(value); @@ -221,7 +226,7 @@ export default createComponent({ if (pickerRef.value) { const values = pickerRef.value .getValues() - .filter((value: PickerObjectOption) => !!value); + .filter((value: AreaColumnOption) => !!value); return parseValues(values); } return []; @@ -265,7 +270,7 @@ export default createComponent({ setValues(); }; - const onChange = (values: PickerObjectOption[], index: number) => { + const onChange = (values: AreaColumnOption[], index: number) => { state.code = values[index].code; setValues(); @@ -273,7 +278,7 @@ export default createComponent({ emit('change', parsedValues, index); }; - const onConfirm = (values: PickerObjectOption[], index: number) => { + const onConfirm = (values: AreaColumnOption[], index: number) => { setValues(); emit('confirm', parseValues(values), index); };