types(AddressEdit): use tsx (#8141)

This commit is contained in:
neverland 2021-02-12 13:22:44 +08:00 committed by GitHub
parent a00f599dc2
commit 2fc8333c45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 95 additions and 74 deletions

View File

@ -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);
}; };

View File

@ -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

View File

@ -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 数据格式

View File

@ -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"

View File

@ -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);
}; };