From 78f667f4522551dddaf3cad22974a42c27721033 Mon Sep 17 00:00:00 2001 From: sunshineLixun <1261142605@qq.com> Date: Thu, 29 Sep 2022 11:37:57 +0800 Subject: [PATCH 1/6] fix: remove unless import --- packages/pro-form/src/BaseForm/hooks/useFormMethods.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/pro-form/src/BaseForm/hooks/useFormMethods.ts b/packages/pro-form/src/BaseForm/hooks/useFormMethods.ts index d9280d7c..5acdd2ac 100644 --- a/packages/pro-form/src/BaseForm/hooks/useFormMethods.ts +++ b/packages/pro-form/src/BaseForm/hooks/useFormMethods.ts @@ -1,4 +1,3 @@ -import { toRaw, isProxy } from 'vue'; import { proxyToRaw } from '@ant-design-vue/pro-utils'; import type { Recordable } from '../../typings'; From d2a15bd5d06cad686651cc5aa9273319944a557b Mon Sep 17 00:00:00 2001 From: sunshineLixun <1261142605@qq.com> Date: Wed, 5 Oct 2022 22:05:19 +0800 Subject: [PATCH 2/6] feat: add ProFormDatePicker --- .../src/components/DatePicker/index.tsx | 61 +++++++++++++++++ .../src/components/DatePicker/types.ts | 12 ++++ .../src/components/Password/index.tsx | 3 +- .../pro-field/src/components/Text/index.tsx | 3 +- packages/pro-field/src/index.tsx | 18 +++++ packages/pro-form/examples/views/ProForm.vue | 11 ++- .../src/components/DatePicker/DatePicker.tsx | 67 +++++++++++++++++++ packages/pro-form/src/components/index.ts | 3 + packages/utils/src/proxyToRaw/index.ts | 1 + 9 files changed, 176 insertions(+), 3 deletions(-) create mode 100644 packages/pro-field/src/components/DatePicker/index.tsx create mode 100644 packages/pro-field/src/components/DatePicker/types.ts create mode 100644 packages/pro-form/src/components/DatePicker/DatePicker.tsx diff --git a/packages/pro-field/src/components/DatePicker/index.tsx b/packages/pro-field/src/components/DatePicker/index.tsx new file mode 100644 index 00000000..bdf3370f --- /dev/null +++ b/packages/pro-field/src/components/DatePicker/index.tsx @@ -0,0 +1,61 @@ +import { defineComponent, type App, DefineComponent, Plugin } from 'vue'; +import { fieldDatePickerProps, FieldDatePickerProps } from './types'; +import { DatePicker } from 'ant-design-vue'; +import { getSlot } from '@ant-design-vue/pro-utils'; + +export const slots = [ + 'suffixIcon', + 'prevIcon', + 'nextIcon', + 'superPrevIcon', + 'superNextIcon', + 'dateRender', + 'renderExtraFooter', + 'monthCellRender', +]; + +const FieldDatePicker = defineComponent({ + name: 'FieldDatePicker', + inheritAttrs: false, + props: fieldDatePickerProps, + slots, + setup(props, { slots }) { + const suffixIcon = getSlot(slots, props.fieldProps as Record, 'suffixIcon'); + const prevIcon = getSlot(slots, props.fieldProps as Record, 'prevIcon'); + const nextIcon = getSlot(slots, props.fieldProps as Record, 'nextIcon'); + const superPrevIcon = getSlot(slots, props.fieldProps as Record, 'superPrevIcon'); + const superNextIcon = getSlot(slots, props.fieldProps as Record, 'superNextIcon'); + const dateRender = getSlot(slots, props.fieldProps as Record, 'dateRender'); + const renderExtraFooter = getSlot(slots, props.fieldProps as Record, 'renderExtraFooter'); + const monthCellRender = getSlot(slots, props.fieldProps as Record, 'monthCellRender'); + return () => { + const { fieldProps } = props; + const { placeholder } = fieldProps || {}; + + return ( + + ); + }; + }, +}); + +FieldDatePicker.install = (app: App) => { + app.component(FieldDatePicker.name, FieldDatePicker); + return app; +}; + +export default FieldDatePicker as DefineComponent & Plugin; diff --git a/packages/pro-field/src/components/DatePicker/types.ts b/packages/pro-field/src/components/DatePicker/types.ts new file mode 100644 index 00000000..278f089e --- /dev/null +++ b/packages/pro-field/src/components/DatePicker/types.ts @@ -0,0 +1,12 @@ +import type { ExtractPropTypes, PropType } from 'vue'; +import type { CommonProps, DatePickerProps } from 'ant-design-vue/es/date-picker/generatePicker/props'; +import { proFieldFC } from '../typings'; + +export const fieldDatePickerProps = { + ...proFieldFC, + fieldProps: { + type: Object as PropType & DatePickerProps>, + }, +}; + +export type FieldDatePickerProps = Partial>; diff --git a/packages/pro-field/src/components/Password/index.tsx b/packages/pro-field/src/components/Password/index.tsx index ceebb87f..4bbf750a 100644 --- a/packages/pro-field/src/components/Password/index.tsx +++ b/packages/pro-field/src/components/Password/index.tsx @@ -11,6 +11,7 @@ const FieldPassword = defineComponent({ setup(props, { slots }) { return () => { const { mode, text, fieldProps } = props; + const placeholder = fieldProps.placeholder || '请输入'; const render = props.render ?? slots.render; const renderFormItem = props.renderFormItem ?? slots?.renderFormItem; @@ -34,7 +35,7 @@ const FieldPassword = defineComponent({ return dom; } if (mode === 'edit' || mode === 'update') { - const renderDom = ; + const renderDom = ; if (renderFormItem) { return renderFormItem(text, { mode, fieldProps }, renderDom); } diff --git a/packages/pro-field/src/components/Text/index.tsx b/packages/pro-field/src/components/Text/index.tsx index b3053af1..3102b628 100644 --- a/packages/pro-field/src/components/Text/index.tsx +++ b/packages/pro-field/src/components/Text/index.tsx @@ -11,6 +11,7 @@ const FieldText = defineComponent({ setup(props, { slots }) { return () => { const { type, mode, text, emptyText, fieldProps } = props; + const placeholder = fieldProps.placeholder || '请输入'; const render = props.render ?? slots?.render; const renderFormItem = props.renderFormItem ?? slots?.renderFormItem; if (mode === 'read') { @@ -27,7 +28,7 @@ const FieldText = defineComponent({ return dom; } if (mode === 'edit' || mode === 'update') { - const renderDom = ; + const renderDom = ; if (renderFormItem) { return renderFormItem(text, { mode, fieldProps }, renderDom); } diff --git a/packages/pro-field/src/index.tsx b/packages/pro-field/src/index.tsx index 3d389f23..65448352 100644 --- a/packages/pro-field/src/index.tsx +++ b/packages/pro-field/src/index.tsx @@ -60,6 +60,10 @@ import FieldSelect from './components/Select'; import { slots as searchSelectSlots } from './components/Select/SearchSelect'; export { FieldSelect, searchSelectProps, searchSelectSlots, type SearchSelectProps }; +import { fieldDatePickerProps, type FieldDatePickerProps } from './components/DatePicker/types'; +import FieldDatePicker, { slots as fieldDatePickerSlots } from './components/DatePicker'; +export { FieldDatePicker, fieldDatePickerProps, fieldDatePickerSlots, FieldDatePickerProps }; + // style import './default.less'; import './style.less'; @@ -100,6 +104,20 @@ const defaultRenderText = ( props: RenderProps // valueTypeMap: Record ): VueNode => { + if (valueType === 'date') { + const { fieldProps } = props; + return ( + + ); + } if (valueType === 'select') { let text = ''; if (dataValue instanceof Array) { diff --git a/packages/pro-form/examples/views/ProForm.vue b/packages/pro-form/examples/views/ProForm.vue index 184cb257..cdc62302 100644 --- a/packages/pro-form/examples/views/ProForm.vue +++ b/packages/pro-form/examples/views/ProForm.vue @@ -158,6 +158,13 @@ }" :request="fetchUser" /> + @@ -166,7 +173,8 @@ import { reactive, ref, FunctionalComponent } from 'vue'; import { PlusOutlined } from '@ant-design/icons-vue'; import { RadioGroup, RadioButton, Switch, Divider, SelectOption, type SelectProps } from 'ant-design-vue'; import type { FormLayout } from 'ant-design-vue/es/form/Form'; -import { ProForm, ProFormText, ProFormPassword, ProFormSelect } from '@ant-design-vue/pro-form'; +import { ProForm, ProFormText, ProFormPassword, ProFormSelect, ProFormDatePicker } from '@ant-design-vue/pro-form'; +import type { Dayjs } from 'dayjs'; let lastFetchId = 0; @@ -201,6 +209,7 @@ const formModel = reactive({ girlName: undefined, lang: undefined, country: undefined, + expirationTime: ref(), }); const sex = ref([ diff --git a/packages/pro-form/src/components/DatePicker/DatePicker.tsx b/packages/pro-form/src/components/DatePicker/DatePicker.tsx new file mode 100644 index 00000000..dd09911b --- /dev/null +++ b/packages/pro-form/src/components/DatePicker/DatePicker.tsx @@ -0,0 +1,67 @@ +import { defineComponent, type PropType, ExtractPropTypes, App, DefineComponent, Plugin } from 'vue'; +import type { CommonProps, DatePickerProps } from 'ant-design-vue/es/date-picker/generatePicker/props'; +import { getSlot } from '@ant-design-vue/pro-utils'; +import { pick } from 'lodash-es'; +import { fieldDatePickerSlots } from '@ant-design-vue/pro-field'; +import ProFormField, { proFormFieldProps } from '../Field'; +import { proFormItemProps } from '../FormItem'; + +const props = { + ...proFormFieldProps, + fieldProps: { + type: Object as PropType & DatePickerProps, 'value'>>, + }, +}; + +export type ProFormDatePickerProps = Partial>; + +export const ProFormDatePicker = defineComponent({ + name: 'ProFormDatePicker', + inheritAttrs: false, + props, + slots: fieldDatePickerSlots, + setup(props, { slots }) { + const formItemProps = { + ...props.formItemProps, + ...pick(props, Object.keys(proFormItemProps)), + }; + const suffixIcon = getSlot(slots, props, 'suffixIcon'); + const prevIcon = getSlot(slots, props, 'prevIcon'); + const nextIcon = getSlot(slots, props, 'nextIcon'); + const superPrevIcon = getSlot(slots, props, 'superPrevIcon'); + const superNextIcon = getSlot(slots, props, 'superNextIcon'); + const dateRender = getSlot(slots, props, 'dateRender'); + const renderExtraFooter = getSlot(slots, props, 'renderExtraFooter'); + const monthCellRender = getSlot(slots, props, 'monthCellRender'); + return () => { + const { fieldProps, colProps } = props; + return ( + + ); + }; + }, +}); + +ProFormDatePicker.install = (app: App) => { + app.component(ProFormDatePicker.name, ProFormDatePicker); + return app; +}; + +export default ProFormDatePicker as DefineComponent & Plugin; diff --git a/packages/pro-form/src/components/index.ts b/packages/pro-form/src/components/index.ts index 5eb68f77..953d8302 100644 --- a/packages/pro-form/src/components/index.ts +++ b/packages/pro-form/src/components/index.ts @@ -6,3 +6,6 @@ export { ProFormPassword, ProFieldPasswordPropsType }; import { ProFormSelect } from './Select'; export { ProFormSelect }; + +import { ProFormDatePicker } from './DatePicker/DatePicker'; +export { ProFormDatePicker }; diff --git a/packages/utils/src/proxyToRaw/index.ts b/packages/utils/src/proxyToRaw/index.ts index 3f67fc9f..b618af40 100644 --- a/packages/utils/src/proxyToRaw/index.ts +++ b/packages/utils/src/proxyToRaw/index.ts @@ -2,6 +2,7 @@ import { toRaw, isProxy } from 'vue'; import type { Recordable } from '../typings'; export const proxyToRaw = (proxy: Recordable) => { + // TOOD: 处理日期格式化 const target: Recordable = {}; for (const key in proxy) { let value = proxy[key]; From b87f5cbc9621fb95cdb5638e6147317ba42fabe3 Mon Sep 17 00:00:00 2001 From: sunshineLixun <1261142605@qq.com> Date: Thu, 6 Oct 2022 21:30:54 +0800 Subject: [PATCH 3/6] feat: add ProFormDatePicker --- .../src/components/DatePicker/index.tsx | 92 +++++++++++-------- .../src/components/DatePicker/types.ts | 4 + .../components/Select/SearchSelect/index.tsx | 39 +------- packages/pro-field/src/index.tsx | 15 ++- packages/pro-form/examples/views/ProForm.vue | 19 ++-- .../src/components/DatePicker/DatePicker.tsx | 20 ++-- .../pro-form/src/components/Select/index.tsx | 26 +++--- packages/utils/src/proxyToRaw/index.ts | 1 - 8 files changed, 100 insertions(+), 116 deletions(-) diff --git a/packages/pro-field/src/components/DatePicker/index.tsx b/packages/pro-field/src/components/DatePicker/index.tsx index bdf3370f..1631a75a 100644 --- a/packages/pro-field/src/components/DatePicker/index.tsx +++ b/packages/pro-field/src/components/DatePicker/index.tsx @@ -1,18 +1,22 @@ import { defineComponent, type App, DefineComponent, Plugin } from 'vue'; +import Dayjs from 'dayjs'; import { fieldDatePickerProps, FieldDatePickerProps } from './types'; import { DatePicker } from 'ant-design-vue'; import { getSlot } from '@ant-design-vue/pro-utils'; +import type { VueNode } from 'ant-design-vue/lib/_util/type'; -export const slots = [ - 'suffixIcon', - 'prevIcon', - 'nextIcon', - 'superPrevIcon', - 'superNextIcon', - 'dateRender', - 'renderExtraFooter', - 'monthCellRender', -]; +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']; const FieldDatePicker = defineComponent({ name: 'FieldDatePicker', @@ -20,35 +24,47 @@ const FieldDatePicker = defineComponent({ props: fieldDatePickerProps, slots, setup(props, { slots }) { - const suffixIcon = getSlot(slots, props.fieldProps as Record, 'suffixIcon'); - const prevIcon = getSlot(slots, props.fieldProps as Record, 'prevIcon'); - const nextIcon = getSlot(slots, props.fieldProps as Record, 'nextIcon'); - const superPrevIcon = getSlot(slots, props.fieldProps as Record, 'superPrevIcon'); - const superNextIcon = getSlot(slots, props.fieldProps as Record, 'superNextIcon'); - const dateRender = getSlot(slots, props.fieldProps as Record, 'dateRender'); - const renderExtraFooter = getSlot(slots, props.fieldProps as Record, 'renderExtraFooter'); - const monthCellRender = getSlot(slots, props.fieldProps as Record, 'monthCellRender'); + const suffixIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record, 'suffixIcon'); + const prevIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record, 'prevIcon'); + const nextIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record, 'nextIcon'); + const superPrevIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record, 'superPrevIcon'); + const superNextIcon = getSlot<() => VueNode>(slots, props.fieldProps as Record, 'superNextIcon'); + + const render = getSlot(slots, props.fieldProps as Record, 'render') as any; + const renderFormItem = getSlot(slots, props.fieldProps as Record, 'renderFormItem') as any; + return () => { - const { fieldProps } = props; - const { placeholder } = fieldProps || {}; - - return ( - - ); + const { mode, text, dateFormat, fieldProps } = props; + const { placeholder, format } = fieldProps || {}; + + if (mode === 'read') { + const dom = formatDate(text, format || dateFormat); + if (render) { + return render(text, { mode, ...fieldProps }, <>{dom}); + } + return <>{dom}; + } + if (mode === 'edit' || mode === 'update') { + const dom = ( + + ); + if (renderFormItem) { + return renderFormItem(text, { mode, ...fieldProps }, dom); + } + return dom; + } + return null; }; }, }); diff --git a/packages/pro-field/src/components/DatePicker/types.ts b/packages/pro-field/src/components/DatePicker/types.ts index 278f089e..ceb5e959 100644 --- a/packages/pro-field/src/components/DatePicker/types.ts +++ b/packages/pro-field/src/components/DatePicker/types.ts @@ -4,6 +4,10 @@ import { proFieldFC } from '../typings'; export const fieldDatePickerProps = { ...proFieldFC, + /** 日期格式化 */ + dateFormat: { + type: String, + }, fieldProps: { type: Object as PropType & DatePickerProps>, }, diff --git a/packages/pro-field/src/components/Select/SearchSelect/index.tsx b/packages/pro-field/src/components/Select/SearchSelect/index.tsx index ab7526e0..23314208 100644 --- a/packages/pro-field/src/components/Select/SearchSelect/index.tsx +++ b/packages/pro-field/src/components/Select/SearchSelect/index.tsx @@ -3,20 +3,7 @@ import { Select } from 'ant-design-vue'; import { searchSelectProps } from './types'; import { getSlot } from '@ant-design-vue/pro-utils'; -export const slots = [ - 'notFoundContent', - 'suffixIcon', - 'itemIcon', - 'removeIcon', - 'clearIcon', - 'dropdownRender', - 'option', - 'placeholder', - 'tagRender', - 'maxTagPlaceholder', - 'optionLabel', - 'default', -]; +export const slots = ['default']; const SearchSelect = defineComponent({ props: searchSelectProps, @@ -24,17 +11,6 @@ const SearchSelect = defineComponent({ setup(props, { slots }) { const searchValue = ref(props.searchValue); - const notFoundContent = getSlot(slots, props, 'notFoundContent'); - const suffixIcon = getSlot(slots, props, 'suffixIcon'); - const itemIcon = getSlot(slots, props, 'itemIcon'); - const removeIcon = getSlot(slots, props, 'removeIcon'); - const clearIcon = getSlot(slots, props, 'clearIcon'); - const dropdownRender = getSlot(slots, props, 'dropdownRender'); - const option = getSlot(slots, props, 'option'); - const placeholder = getSlot(slots, props, 'placeholder'); - const tagRender = getSlot(slots, props, 'tagRender'); - const maxTagPlaceholder = getSlot(slots, props, 'maxTagPlaceholder'); - const optionLabel = getSlot(slots, props, 'optionLabel'); const children = getSlot(slots, props, 'default'); return () => { @@ -43,6 +19,7 @@ const SearchSelect = defineComponent({ labelInValue, autoClearSearchValue = true, showSearch, + placeholder, onSearch, onClear, fetchData, @@ -52,22 +29,12 @@ const SearchSelect = defineComponent({ return (