Skip to content

feat: 新增DatePicker原子化组件 #252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Nov 10, 2022
32 changes: 26 additions & 6 deletions packages/pro-field/src/components/DatePicker/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { defineComponent, type App, DefineComponent, Plugin } from 'vue';
import Dayjs from 'dayjs';
import dayjs from 'dayjs';
import { fieldDatePickerProps, FieldDatePickerProps } from './types';
import { DatePicker } from 'ant-design-vue';
import { getSlot } from '@ant-design-vue/pro-utils';
Expand All @@ -10,13 +10,22 @@ const formatDate = (text: any, format: any) => {
return '-';
}
if (typeof format === 'function') {
return format(Dayjs(text));
return format(dayjs(text));
} else {
return Dayjs(text).format(format || 'YYYY-MM-DD');
return dayjs(text).format(format || 'YYYY-MM-DD');
}
};

export const slots = ['suffixIcon', 'prevIcon', 'nextIcon', 'superPrevIcon', 'superNextIcon'];
export const slots = [
'suffixIcon',
'prevIcon',
'nextIcon',
'superPrevIcon',
'superNextIcon',
'renderExtraFooter',
'dateRender',
'monthCellRender',
];

const FieldDatePicker = defineComponent({
name: 'FieldDatePicker',
Expand All @@ -29,16 +38,23 @@ const FieldDatePicker = defineComponent({
const nextIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record<string, any>, 'nextIcon');
const superPrevIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record<string, any>, 'superPrevIcon');
const superNextIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record<string, any>, 'superNextIcon');
const renderExtraFooter = getSlot<() => VueNode>(
slots,
props.fieldProps as Record<string, any>,
'renderExtraFooter'
);
const dateRender = getSlot<() => VueNode>(slots, props.fieldProps as Record<string, any>, 'dateRender');
const monthCellRender = getSlot<() => VueNode>(slots, props.fieldProps as Record<string, any>, 'monthCellRender');

const render = getSlot(slots, props.fieldProps as Record<string, any>, 'render') as any;
const renderFormItem = getSlot(slots, props.fieldProps as Record<string, any>, 'renderFormItem') as any;

return () => {
const { mode, text, dateFormat, fieldProps } = props;
const { mode, text, fieldProps } = props;
const { placeholder, format } = fieldProps || {};

if (mode === 'read') {
const dom = formatDate(text, format || dateFormat);
const dom = formatDate(text, format);
if (render) {
return render(text, { mode, ...fieldProps }, <>{dom}</>);
}
Expand All @@ -53,8 +69,12 @@ const FieldDatePicker = defineComponent({
nextIcon,
superPrevIcon,
superNextIcon,
renderExtraFooter,
dateRender,
monthCellRender,
}}
{...fieldProps}
format={format}
placeholder={placeholder || '请选择'}
allowClear
/>
Expand Down
10 changes: 5 additions & 5 deletions packages/pro-field/src/components/DatePicker/types.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import type { ExtractPropTypes, PropType } from 'vue';
import type { Dayjs } from 'dayjs';
import type { CommonProps, DatePickerProps } from 'ant-design-vue/es/date-picker/generatePicker/props';
import { proFieldFC } from '../typings';

export const fieldDatePickerProps = {
...proFieldFC,
/** 日期格式化 */
dateFormat: {
type: String,
},
fieldProps: {
type: Object as PropType<CommonProps<any> & DatePickerProps<any>>,
type: Object as PropType<CommonProps<Dayjs> & DatePickerProps<Dayjs>>,
},
picker: {
type: String as PropType<CommonProps<Dayjs>['picker']>,
},
};

Expand Down
103 changes: 103 additions & 0 deletions packages/pro-field/src/components/RangePicker/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { defineComponent, type App, DefineComponent, Plugin } from 'vue';
import dayjs from 'dayjs';
import { fieldRangePickerProps, FieldRangePickerProps, RangesType } from './types';
import { RangePicker } from 'ant-design-vue';
import { getSlot } from '@ant-design-vue/pro-utils';
import type { VueNode } from 'ant-design-vue/lib/_util/type';

const formatDate = (text: any, format: any) => {
if (!text) {
return '-';
}
if (typeof format === 'function') {
return format(dayjs(text));
} else {
return dayjs(text).format(format || 'YYYY-MM-DD');
}
};

export const slots = [
'suffixIcon',
'prevIcon',
'nextIcon',
'superPrevIcon',
'superNextIcon',
'renderExtraFooter',
'dateRender',
];

const FieldRangePicker = defineComponent({
name: 'FieldRangePicker',
inheritAttrs: false,
props: fieldRangePickerProps,
slots,
setup(props, { slots }) {
const suffixIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record<string, any>, 'suffixIcon');
const prevIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record<string, any>, 'prevIcon');
const nextIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record<string, any>, 'nextIcon');
const superPrevIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record<string, any>, 'superPrevIcon');
const superNextIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record<string, any>, 'superNextIcon');
const renderExtraFooter = getSlot<() => VueNode>(
slots,
props.fieldProps as Record<string, any>,
'renderExtraFooter'
);
const dateRender = getSlot<() => VueNode>(slots, props.fieldProps as Record<string, any>, 'dateRender');

const render = getSlot(slots, props.fieldProps as Record<string, any>, 'render') as any;
const renderFormItem = getSlot(slots, props.fieldProps as Record<string, any>, 'renderFormItem') as any;

return () => {
const { mode, text, fieldProps } = props;
const { placeholder, ranges, format = 'YYYY-MM-DD' } = fieldProps || {};
const [startText, endText] = Array.isArray(text) ? text : [];

if (mode === 'read') {
const parsedStartText: string = startText ? formatDate(startText, format) : '';
const parsedEndText: string = endText ? formatDate(endText, format) : '';
const dom = (
<div>
<div>{parsedStartText || '-'}</div>
<div>{parsedEndText || '-'}</div>
</div>
);
if (render) {
return render(text, { mode, ...fieldProps }, <>{dom}</>);
}
return dom;
}
if (mode === 'edit' || mode === 'update') {
const dom = (
<RangePicker
v-slots={{
suffixIcon,
prevIcon,
nextIcon,
superPrevIcon,
superNextIcon,
renderExtraFooter,
dateRender,
}}
{...fieldProps}
format={format}
ranges={ranges as RangesType}
placeholder={placeholder || ['请选择', '请选择']}
allowClear
/>
);
if (renderFormItem) {
return renderFormItem(text, { mode, ...fieldProps }, dom);
}
return dom;
}
return null;
};
},
});

FieldRangePicker.install = (app: App) => {
app.component(FieldRangePicker.name, FieldRangePicker);
return app;
};

export default FieldRangePicker as DefineComponent<FieldRangePickerProps> & Plugin;
21 changes: 21 additions & 0 deletions packages/pro-field/src/components/RangePicker/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { ExtractPropTypes, PropType } from 'vue';
import type { Dayjs } from 'dayjs';
import { rangePickerProps, type CommonProps } from 'ant-design-vue/es/date-picker/generatePicker/props';
import { proFieldFC } from '../typings';

const rangeProps = rangePickerProps<Dayjs>();

export type RangePickerProps = Partial<ExtractPropTypes<typeof rangeProps>>;

export const fieldRangePickerProps = {
...proFieldFC,
fieldProps: {
type: Object as PropType<CommonProps<Dayjs> & RangePickerProps>,
},
};

export type FieldRangePickerProps = Partial<ExtractPropTypes<typeof fieldRangePickerProps>>;

export type RangePickerValueType = [string, string] | [Dayjs, Dayjs];

export type RangesType = Record<string, [Dayjs, Dayjs] | (() => [Dayjs, Dayjs])>;
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getSlot } from '@ant-design-vue/pro-utils';
export const slots = ['default'];

const SearchSelect = defineComponent({
inheritAttrs: false,
props: searchSelectProps,
slots,
setup(props, { slots }) {
Expand Down
10 changes: 3 additions & 7 deletions packages/pro-field/src/components/Select/hooks/useFetchData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,9 @@ export const useFetchData = (props: FieldSelectProps) => {
const { request } = props;
watchEffect(() => {
loading.value = true;
request(
{
...props.params,
keyWords: defaultKeyWords.value,
},
props
)
request({
keyWords: defaultKeyWords.value,
})
.then((data) => {
options.value = data;
})
Expand Down
5 changes: 1 addition & 4 deletions packages/pro-field/src/components/Select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ export const fieldSelectProps = {
fieldProps: {
type: Object as PropType<SearchSelectProps>,
},
// 请求参数
params: {
type: Object as PropType<Record<string, any>>,
},
// 请求
request: {
type: Function as PropType<ProFieldRequestData>,
Expand All @@ -24,6 +20,7 @@ export const fieldSelectProps = {
export type FieldSelectProps = Partial<ExtractPropTypes<typeof fieldSelectProps>>;

const FieldSelect = defineComponent({
inheritAttrs: false,
props: fieldSelectProps,
slots: ['render', 'renderFormItem'],
setup(props, { slots }) {
Expand Down
69 changes: 69 additions & 0 deletions packages/pro-field/src/components/TimePicker/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { defineComponent, type App, DefineComponent, Plugin } from 'vue';
import dayjs from 'dayjs';
import { fieldTimePickerProps, FieldTimePickerProps } from './types';
import { TimePicker } from 'ant-design-vue';
import { getSlot, VueText } from '@ant-design-vue/pro-utils';
import type { VueNode } from 'ant-design-vue/lib/_util/type';

export const slots = ['renderExtraFooter', 'suffixIcon', 'clearIcon'];

const FieldTimePicker = defineComponent({
name: 'FieldDatePicker',
inheritAttrs: false,
props: fieldTimePickerProps,
slots,
setup(props, { slots }) {
const suffixIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record<string, any>, 'suffixIcon');
const clearIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record<string, any>, 'clearIcon');
const renderExtraFooter = getSlot<() => VueNode>(
slots,
props.fieldProps as Record<string, any>,
'renderExtraFooter'
);

const render = getSlot(slots, props.fieldProps as Record<string, any>, 'render') as any;
const renderFormItem = getSlot(slots, props.fieldProps as Record<string, any>, 'renderFormItem') as any;

return () => {
const { mode, text, fieldProps } = props;
const { placeholder } = fieldProps || {};

const finalFormat = fieldProps?.format || 'HH:mm:ss';

if (mode === 'read') {
const dom = <span>{text ? dayjs(text as VueText, finalFormat).format(finalFormat) : '-'}</span>;
if (render) {
return render(text, { mode, ...fieldProps }, <span>{dom}</span>);
}
return dom;
}
if (mode === 'edit' || mode === 'update') {
const dom = (
<TimePicker
v-slots={{
suffixIcon,
renderExtraFooter,
clearIcon,
}}
{...fieldProps}
format={finalFormat}
placeholder={placeholder || '请选择'}
allowClear
/>
);
if (renderFormItem) {
return renderFormItem(text, { mode, ...fieldProps }, dom);
}
return dom;
}
return null;
};
},
});

FieldTimePicker.install = (app: App) => {
app.component(FieldTimePicker.name, FieldTimePicker);
return app;
};

export default FieldTimePicker as DefineComponent<FieldTimePickerProps> & Plugin;
13 changes: 13 additions & 0 deletions packages/pro-field/src/components/TimePicker/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { ExtractPropTypes, PropType } from 'vue';
import type { Dayjs } from 'dayjs';
import type { TimePickerProps } from 'ant-design-vue/es/time-picker/time-picker';
import { proFieldFC } from '../typings';

export const fieldTimePickerProps = {
...proFieldFC,
fieldProps: {
type: Object as PropType<TimePickerProps<Dayjs>>,
},
};

export type FieldTimePickerProps = Partial<ExtractPropTypes<typeof fieldTimePickerProps>>;
Loading