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