From 9928a656aadc8afaeb81c5475b8f627398d69e65 Mon Sep 17 00:00:00 2001 From: dap <15891557205@163.com> Date: Mon, 30 Sep 2024 08:43:53 +0800 Subject: [PATCH 1/4] chore: demo of customizing form layout using tailwind --- playground/src/views/examples/form/basic.vue | 100 +++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/playground/src/views/examples/form/basic.vue b/playground/src/views/examples/form/basic.vue index a92ec258d26..50a3caaeeb0 100644 --- a/playground/src/views/examples/form/basic.vue +++ b/playground/src/views/examples/form/basic.vue @@ -223,6 +223,102 @@ const [BaseForm, baseFormApi] = useVbenForm({ wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3', }); +const [CustomLayoutForm] = useVbenForm({ + // 所有表单项共用,可单独在表单内覆盖 + commonConfig: { + // 所有表单项 + componentProps: { + class: 'w-full', + }, + }, + layout: 'horizontal', + schema: [ + { + component: 'Input', + componentProps: { + placeholder: '请输入', + }, + fieldName: 'field1', + label: '字符串', + }, + { + component: 'Input', + componentProps: { + placeholder: '请输入', + }, + fieldName: 'field2', + label: '字符串', + }, + { + component: 'Input', + componentProps: { + placeholder: '请输入', + }, + fieldName: 'field3', + label: '字符串', + }, + { + component: 'Input', + componentProps: { + placeholder: '请输入', + }, + fieldName: 'field4', + label: '字符串', + }, + { + component: 'Input', + componentProps: { + placeholder: '请输入', + }, + fieldName: 'field5', + // 从第三列开始 相当于中间空了一列 + formItemClass: 'col-start-3', + label: '前面空了一列', + }, + { + component: 'Input', + componentProps: { + placeholder: '请输入', + }, + fieldName: 'field6', + // 占满三列空间 + formItemClass: 'col-span-3', + label: '占满三列', + }, + { + component: 'Input', + componentProps: { + placeholder: '请输入', + }, + fieldName: 'field7', + // 占满2列空间 从第二列开始 相当于前面空了一列 + formItemClass: 'col-span-2 col-start-2', + label: '占满2列', + }, + { + component: 'Input', + componentProps: { + placeholder: '请输入', + }, + fieldName: 'field8', + // 左右留空 + formItemClass: 'col-start-2', + label: '左右留空', + }, + { + component: 'Input', + componentProps: { + placeholder: '请输入', + }, + fieldName: 'field9', + formItemClass: 'col-start-1', + label: '占满2列', + }, + ], + // 一共三列 + wrapperClass: 'lg:grid-cols-3', +}); + function onSubmit(values: Record) { message.success({ content: `form values: ${JSON.stringify(values)}`, @@ -256,6 +352,7 @@ function handleSetFormValue() { + + + From 663409b32d929087f7d05ce076be5ef675d10a73 Mon Sep 17 00:00:00 2001 From: dap <15891557205@163.com> Date: Mon, 30 Sep 2024 11:23:04 +0800 Subject: [PATCH 2/4] perf: default placeholder for input and select components --- apps/web-antd/src/adapter/form.ts | 30 +++++++++---- packages/locales/src/langs/en-US.json | 4 ++ packages/locales/src/langs/zh-CN.json | 4 ++ playground/src/adapter/form.ts | 30 +++++++++---- playground/src/views/examples/form/basic.vue | 47 +++++--------------- 5 files changed, 62 insertions(+), 53 deletions(-) diff --git a/apps/web-antd/src/adapter/form.ts b/apps/web-antd/src/adapter/form.ts index b55b9b0a6a1..c84884c07e8 100644 --- a/apps/web-antd/src/adapter/form.ts +++ b/apps/web-antd/src/adapter/form.ts @@ -4,7 +4,7 @@ import type { VbenFormProps, } from '@vben/common-ui'; -import { h } from 'vue'; +import { type Component, h } from 'vue'; import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui'; import { $t } from '@vben/locales'; @@ -57,6 +57,20 @@ export type FormComponentType = | 'Upload' | BaseFormComponentType; +const withInputPlaceholder = (component: Component) => { + return (props: any, { attrs, slots }: any) => { + const placeholder = props?.placeholder || $t('placeholder.input'); + return h(component, { ...props, attrs, placeholder }, slots); + }; +}; + +const withSelectPlaceholder = (component: Component) => { + return (props: any, { attrs, slots }: any) => { + const placeholder = props?.placeholder || $t('placeholder.select'); + return h(component, { ...props, attrs, placeholder }, slots); + }; +}; + // 初始化表单组件,并注册到form组件内部 setupVbenForm({ components: { @@ -73,20 +87,20 @@ setupVbenForm({ return h(Button, { ...props, attrs, type: 'primary' }, slots); }, Divider, - Input, - InputNumber, - InputPassword, - Mentions, + Input: withInputPlaceholder(Input), + InputNumber: withInputPlaceholder(InputNumber), + InputPassword: withInputPlaceholder(InputPassword), + Mentions: withInputPlaceholder(Mentions), Radio, RadioGroup, RangePicker, Rate, - Select, + Select: withSelectPlaceholder(Select), Space, Switch, - Textarea, + Textarea: withInputPlaceholder(Textarea), TimePicker, - TreeSelect, + TreeSelect: withSelectPlaceholder(TreeSelect), Upload, }, config: { diff --git a/packages/locales/src/langs/en-US.json b/packages/locales/src/langs/en-US.json index e9503cf4dba..6b42d8488b0 100644 --- a/packages/locales/src/langs/en-US.json +++ b/packages/locales/src/langs/en-US.json @@ -58,6 +58,10 @@ "required": "Please enter {0}", "selectRequired": "Please select {0}" }, + "placeholder": { + "input": "Please enter", + "select": "Please select" + }, "widgets": { "document": "Document", "qa": "Q&A", diff --git a/packages/locales/src/langs/zh-CN.json b/packages/locales/src/langs/zh-CN.json index ef71a5547f2..b5a24d7cd66 100644 --- a/packages/locales/src/langs/zh-CN.json +++ b/packages/locales/src/langs/zh-CN.json @@ -58,6 +58,10 @@ "required": "请输入{0}", "selectRequired": "请选择{0}" }, + "placeholder": { + "input": "请输入", + "select": "请选择" + }, "widgets": { "document": "文档", "qa": "问题 & 帮助", diff --git a/playground/src/adapter/form.ts b/playground/src/adapter/form.ts index b55b9b0a6a1..c84884c07e8 100644 --- a/playground/src/adapter/form.ts +++ b/playground/src/adapter/form.ts @@ -4,7 +4,7 @@ import type { VbenFormProps, } from '@vben/common-ui'; -import { h } from 'vue'; +import { type Component, h } from 'vue'; import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui'; import { $t } from '@vben/locales'; @@ -57,6 +57,20 @@ export type FormComponentType = | 'Upload' | BaseFormComponentType; +const withInputPlaceholder = (component: Component) => { + return (props: any, { attrs, slots }: any) => { + const placeholder = props?.placeholder || $t('placeholder.input'); + return h(component, { ...props, attrs, placeholder }, slots); + }; +}; + +const withSelectPlaceholder = (component: Component) => { + return (props: any, { attrs, slots }: any) => { + const placeholder = props?.placeholder || $t('placeholder.select'); + return h(component, { ...props, attrs, placeholder }, slots); + }; +}; + // 初始化表单组件,并注册到form组件内部 setupVbenForm({ components: { @@ -73,20 +87,20 @@ setupVbenForm({ return h(Button, { ...props, attrs, type: 'primary' }, slots); }, Divider, - Input, - InputNumber, - InputPassword, - Mentions, + Input: withInputPlaceholder(Input), + InputNumber: withInputPlaceholder(InputNumber), + InputPassword: withInputPlaceholder(InputPassword), + Mentions: withInputPlaceholder(Mentions), Radio, RadioGroup, RangePicker, Rate, - Select, + Select: withSelectPlaceholder(Select), Space, Switch, - Textarea, + Textarea: withInputPlaceholder(Textarea), TimePicker, - TreeSelect, + TreeSelect: withSelectPlaceholder(TreeSelect), Upload, }, config: { diff --git a/playground/src/views/examples/form/basic.vue b/playground/src/views/examples/form/basic.vue index 50a3caaeeb0..ac10e446d5e 100644 --- a/playground/src/views/examples/form/basic.vue +++ b/playground/src/views/examples/form/basic.vue @@ -234,62 +234,41 @@ const [CustomLayoutForm] = useVbenForm({ layout: 'horizontal', schema: [ { - component: 'Input', - componentProps: { - placeholder: '请输入', - }, + component: 'Select', fieldName: 'field1', label: '字符串', }, { - component: 'Input', - componentProps: { - placeholder: '请输入', - }, + component: 'TreeSelect', fieldName: 'field2', label: '字符串', }, { - component: 'Input', - componentProps: { - placeholder: '请输入', - }, + component: 'Mentions', fieldName: 'field3', label: '字符串', }, { component: 'Input', - componentProps: { - placeholder: '请输入', - }, fieldName: 'field4', label: '字符串', }, { - component: 'Input', - componentProps: { - placeholder: '请输入', - }, + component: 'InputNumber', fieldName: 'field5', // 从第三列开始 相当于中间空了一列 formItemClass: 'col-start-3', label: '前面空了一列', }, { - component: 'Input', - componentProps: { - placeholder: '请输入', - }, + component: 'Textarea', fieldName: 'field6', - // 占满三列空间 - formItemClass: 'col-span-3', + // 占满三列空间 基线对齐 + formItemClass: 'col-span-3 items-baseline', label: '占满三列', }, { component: 'Input', - componentProps: { - placeholder: '请输入', - }, fieldName: 'field7', // 占满2列空间 从第二列开始 相当于前面空了一列 formItemClass: 'col-span-2 col-start-2', @@ -297,26 +276,20 @@ const [CustomLayoutForm] = useVbenForm({ }, { component: 'Input', - componentProps: { - placeholder: '请输入', - }, fieldName: 'field8', // 左右留空 formItemClass: 'col-start-2', label: '左右留空', }, { - component: 'Input', - componentProps: { - placeholder: '请输入', - }, + component: 'InputPassword', fieldName: 'field9', formItemClass: 'col-start-1', - label: '占满2列', + label: '字符串', }, ], // 一共三列 - wrapperClass: 'lg:grid-cols-3', + wrapperClass: 'grid-cols-3', }); function onSubmit(values: Record) { From 6f5304c2c510cf1bebe043bb939d2093a8989f20 Mon Sep 17 00:00:00 2001 From: dap <15891557205@163.com> Date: Mon, 30 Sep 2024 11:37:31 +0800 Subject: [PATCH 3/4] chore: update ts type --- apps/web-antd/src/adapter/form.ts | 10 +++++----- playground/src/adapter/form.ts | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/web-antd/src/adapter/form.ts b/apps/web-antd/src/adapter/form.ts index c84884c07e8..be28dec93c6 100644 --- a/apps/web-antd/src/adapter/form.ts +++ b/apps/web-antd/src/adapter/form.ts @@ -4,7 +4,7 @@ import type { VbenFormProps, } from '@vben/common-ui'; -import { type Component, h } from 'vue'; +import { type Component, h, type SetupContext } from 'vue'; import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui'; import { $t } from '@vben/locales'; @@ -57,15 +57,15 @@ export type FormComponentType = | 'Upload' | BaseFormComponentType; -const withInputPlaceholder = (component: Component) => { - return (props: any, { attrs, slots }: any) => { +const withInputPlaceholder = (component: T) => { + return (props: any, { attrs, slots }: Omit) => { const placeholder = props?.placeholder || $t('placeholder.input'); return h(component, { ...props, attrs, placeholder }, slots); }; }; -const withSelectPlaceholder = (component: Component) => { - return (props: any, { attrs, slots }: any) => { +const withSelectPlaceholder = (component: T) => { + return (props: any, { attrs, slots }: Omit) => { const placeholder = props?.placeholder || $t('placeholder.select'); return h(component, { ...props, attrs, placeholder }, slots); }; diff --git a/playground/src/adapter/form.ts b/playground/src/adapter/form.ts index c84884c07e8..be28dec93c6 100644 --- a/playground/src/adapter/form.ts +++ b/playground/src/adapter/form.ts @@ -4,7 +4,7 @@ import type { VbenFormProps, } from '@vben/common-ui'; -import { type Component, h } from 'vue'; +import { type Component, h, type SetupContext } from 'vue'; import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui'; import { $t } from '@vben/locales'; @@ -57,15 +57,15 @@ export type FormComponentType = | 'Upload' | BaseFormComponentType; -const withInputPlaceholder = (component: Component) => { - return (props: any, { attrs, slots }: any) => { +const withInputPlaceholder = (component: T) => { + return (props: any, { attrs, slots }: Omit) => { const placeholder = props?.placeholder || $t('placeholder.input'); return h(component, { ...props, attrs, placeholder }, slots); }; }; -const withSelectPlaceholder = (component: Component) => { - return (props: any, { attrs, slots }: any) => { +const withSelectPlaceholder = (component: T) => { + return (props: any, { attrs, slots }: Omit) => { const placeholder = props?.placeholder || $t('placeholder.select'); return h(component, { ...props, attrs, placeholder }, slots); }; From e1004d2f563a1175ed7768b93085e09823044936 Mon Sep 17 00:00:00 2001 From: dap <15891557205@163.com> Date: Mon, 30 Sep 2024 15:40:20 +0800 Subject: [PATCH 4/4] chore: extract public methods --- apps/web-antd/src/adapter/form.ts | 28 ++++++++++++---------------- playground/src/adapter/form.ts | 28 ++++++++++++---------------- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/apps/web-antd/src/adapter/form.ts b/apps/web-antd/src/adapter/form.ts index be28dec93c6..b52a8840be3 100644 --- a/apps/web-antd/src/adapter/form.ts +++ b/apps/web-antd/src/adapter/form.ts @@ -57,16 +57,12 @@ export type FormComponentType = | 'Upload' | BaseFormComponentType; -const withInputPlaceholder = (component: T) => { +const withDefaultPlaceholder = ( + component: T, + type: 'input' | 'select', +) => { return (props: any, { attrs, slots }: Omit) => { - const placeholder = props?.placeholder || $t('placeholder.input'); - return h(component, { ...props, attrs, placeholder }, slots); - }; -}; - -const withSelectPlaceholder = (component: T) => { - return (props: any, { attrs, slots }: Omit) => { - const placeholder = props?.placeholder || $t('placeholder.select'); + const placeholder = props?.placeholder || $t(`placeholder.${type}`); return h(component, { ...props, attrs, placeholder }, slots); }; }; @@ -87,20 +83,20 @@ setupVbenForm({ return h(Button, { ...props, attrs, type: 'primary' }, slots); }, Divider, - Input: withInputPlaceholder(Input), - InputNumber: withInputPlaceholder(InputNumber), - InputPassword: withInputPlaceholder(InputPassword), - Mentions: withInputPlaceholder(Mentions), + Input: withDefaultPlaceholder(Input, 'input'), + InputNumber: withDefaultPlaceholder(InputNumber, 'input'), + InputPassword: withDefaultPlaceholder(InputPassword, 'input'), + Mentions: withDefaultPlaceholder(Mentions, 'input'), Radio, RadioGroup, RangePicker, Rate, - Select: withSelectPlaceholder(Select), + Select: withDefaultPlaceholder(Select, 'select'), Space, Switch, - Textarea: withInputPlaceholder(Textarea), + Textarea: withDefaultPlaceholder(Textarea, 'input'), TimePicker, - TreeSelect: withSelectPlaceholder(TreeSelect), + TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'), Upload, }, config: { diff --git a/playground/src/adapter/form.ts b/playground/src/adapter/form.ts index be28dec93c6..b52a8840be3 100644 --- a/playground/src/adapter/form.ts +++ b/playground/src/adapter/form.ts @@ -57,16 +57,12 @@ export type FormComponentType = | 'Upload' | BaseFormComponentType; -const withInputPlaceholder = (component: T) => { +const withDefaultPlaceholder = ( + component: T, + type: 'input' | 'select', +) => { return (props: any, { attrs, slots }: Omit) => { - const placeholder = props?.placeholder || $t('placeholder.input'); - return h(component, { ...props, attrs, placeholder }, slots); - }; -}; - -const withSelectPlaceholder = (component: T) => { - return (props: any, { attrs, slots }: Omit) => { - const placeholder = props?.placeholder || $t('placeholder.select'); + const placeholder = props?.placeholder || $t(`placeholder.${type}`); return h(component, { ...props, attrs, placeholder }, slots); }; }; @@ -87,20 +83,20 @@ setupVbenForm({ return h(Button, { ...props, attrs, type: 'primary' }, slots); }, Divider, - Input: withInputPlaceholder(Input), - InputNumber: withInputPlaceholder(InputNumber), - InputPassword: withInputPlaceholder(InputPassword), - Mentions: withInputPlaceholder(Mentions), + Input: withDefaultPlaceholder(Input, 'input'), + InputNumber: withDefaultPlaceholder(InputNumber, 'input'), + InputPassword: withDefaultPlaceholder(InputPassword, 'input'), + Mentions: withDefaultPlaceholder(Mentions, 'input'), Radio, RadioGroup, RangePicker, Rate, - Select: withSelectPlaceholder(Select), + Select: withDefaultPlaceholder(Select, 'select'), Space, Switch, - Textarea: withInputPlaceholder(Textarea), + Textarea: withDefaultPlaceholder(Textarea, 'input'), TimePicker, - TreeSelect: withSelectPlaceholder(TreeSelect), + TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'), Upload, }, config: {