feat(VForm): Add VForm component
This commit is contained in:
parent
d16a5aa75e
commit
448ac5293e
|
@ -6128,8 +6128,8 @@ packages:
|
||||||
vue-i18n:
|
vue-i18n:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@intlify/message-compiler': registry.npmmirror.com/@intlify/message-compiler/9.2.0-beta.23
|
'@intlify/message-compiler': registry.npmmirror.com/@intlify/message-compiler/9.2.0-beta.25
|
||||||
'@intlify/shared': registry.npmmirror.com/@intlify/shared/9.2.0-beta.23
|
'@intlify/shared': registry.npmmirror.com/@intlify/shared/9.2.0-beta.25
|
||||||
jsonc-eslint-parser: registry.npmmirror.com/jsonc-eslint-parser/1.4.1
|
jsonc-eslint-parser: registry.npmmirror.com/jsonc-eslint-parser/1.4.1
|
||||||
source-map: registry.nlark.com/source-map/0.6.1
|
source-map: registry.nlark.com/source-map/0.6.1
|
||||||
vue-i18n: registry.npmmirror.com/vue-i18n/9.1.9_vue@3.2.24
|
vue-i18n: registry.npmmirror.com/vue-i18n/9.1.9_vue@3.2.24
|
||||||
|
@ -6185,18 +6185,18 @@ packages:
|
||||||
source-map: registry.nlark.com/source-map/0.6.1
|
source-map: registry.nlark.com/source-map/0.6.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
registry.npmmirror.com/@intlify/message-compiler/9.2.0-beta.23:
|
registry.npmmirror.com/@intlify/message-compiler/9.2.0-beta.25:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
integrity: sha512-qmGN8k5yGGdZ5St8yg8U4Tg2K9Sc6h3BhWCdJKAqQVs5jnfZG+nMtsLVgnJUWkDvhjzyg7/rEOhHm2uJcu4vjw==,
|
integrity: sha512-/YMG6LmQLvD8uHCJvWLaK0t8exYbek3ya4BZZ99AcM5+JC/JRdLIK8WiVJnGpfrvleQArxvHed4GokS+oWZ5rQ==,
|
||||||
registry: https://registry.npm.taobao.org/,
|
registry: https://registry.npm.taobao.org/,
|
||||||
tarball: https://registry.npmmirror.com/@intlify/message-compiler/download/@intlify/message-compiler-9.2.0-beta.23.tgz
|
tarball: https://registry.npmmirror.com/@intlify/message-compiler/download/@intlify/message-compiler-9.2.0-beta.25.tgz
|
||||||
}
|
}
|
||||||
name: '@intlify/message-compiler'
|
name: '@intlify/message-compiler'
|
||||||
version: 9.2.0-beta.23
|
version: 9.2.0-beta.25
|
||||||
engines: { node: '>= 12' }
|
engines: { node: '>= 12' }
|
||||||
dependencies:
|
dependencies:
|
||||||
'@intlify/shared': registry.npmmirror.com/@intlify/shared/9.2.0-beta.23
|
'@intlify/shared': registry.npmmirror.com/@intlify/shared/9.2.0-beta.25
|
||||||
source-map: registry.nlark.com/source-map/0.6.1
|
source-map: registry.nlark.com/source-map/0.6.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
@ -6240,15 +6240,15 @@ packages:
|
||||||
engines: { node: '>= 10' }
|
engines: { node: '>= 10' }
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
registry.npmmirror.com/@intlify/shared/9.2.0-beta.23:
|
registry.npmmirror.com/@intlify/shared/9.2.0-beta.25:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
integrity: sha512-3aELL2KTp1MWKGm2gIUKSagthgKzcK5hpQEFzOwkJ1SAthpTXR7BHeWGEaD+Lj+Pbiz3U8cspvp8s2lFWVbYxg==,
|
integrity: sha512-I2L05aWh0azr5KwQjLV7gMTN0SrdglgMAfpJniT53Pvvc8l+OTs8IEhdPCQwsbgOravpWt14O7m3deOzw3ln6w==,
|
||||||
registry: https://registry.npm.taobao.org/,
|
registry: https://registry.npm.taobao.org/,
|
||||||
tarball: https://registry.npmmirror.com/@intlify/shared/download/@intlify/shared-9.2.0-beta.23.tgz
|
tarball: https://registry.npmmirror.com/@intlify/shared/download/@intlify/shared-9.2.0-beta.25.tgz
|
||||||
}
|
}
|
||||||
name: '@intlify/shared'
|
name: '@intlify/shared'
|
||||||
version: 9.2.0-beta.23
|
version: 9.2.0-beta.25
|
||||||
engines: { node: '>= 12' }
|
engines: { node: '>= 12' }
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
@ -6274,7 +6274,7 @@ packages:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@intlify/bundle-utils': registry.npmmirror.com/@intlify/bundle-utils/2.2.0_vue-i18n@9.1.9
|
'@intlify/bundle-utils': registry.npmmirror.com/@intlify/bundle-utils/2.2.0_vue-i18n@9.1.9
|
||||||
'@intlify/shared': registry.npmmirror.com/@intlify/shared/9.2.0-beta.23
|
'@intlify/shared': registry.npmmirror.com/@intlify/shared/9.2.0-beta.25
|
||||||
'@rollup/pluginutils': registry.nlark.com/@rollup/pluginutils/4.1.1
|
'@rollup/pluginutils': registry.nlark.com/@rollup/pluginutils/4.1.1
|
||||||
debug: registry.npmmirror.com/debug/4.3.3
|
debug: registry.npmmirror.com/debug/4.3.3
|
||||||
fast-glob: registry.nlark.com/fast-glob/3.2.7
|
fast-glob: registry.nlark.com/fast-glob/3.2.7
|
||||||
|
@ -8693,13 +8693,12 @@ packages:
|
||||||
registry.npmmirror.com/lodash/4.17.21:
|
registry.npmmirror.com/lodash/4.17.21:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
integrity: sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw=,
|
integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==,
|
||||||
registry: https://registry.npm.taobao.org/,
|
registry: https://registry.npm.taobao.org/,
|
||||||
tarball: https://registry.npmmirror.com/lodash/download/lodash-4.17.21.tgz
|
tarball: https://registry.npmmirror.com/lodash/download/lodash-4.17.21.tgz
|
||||||
}
|
}
|
||||||
name: lodash
|
name: lodash
|
||||||
version: 4.17.21
|
version: 4.17.21
|
||||||
dev: false
|
|
||||||
|
|
||||||
registry.npmmirror.com/log-update/4.0.0:
|
registry.npmmirror.com/log-update/4.0.0:
|
||||||
resolution:
|
resolution:
|
||||||
|
@ -10291,7 +10290,7 @@ packages:
|
||||||
version: 0.3.2
|
version: 0.3.2
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys/1.3.0
|
eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys/1.3.0
|
||||||
lodash: registry.nlark.com/lodash/4.17.21
|
lodash: registry.npmmirror.com/lodash/4.17.21
|
||||||
yaml: registry.npmmirror.com/yaml/1.10.2
|
yaml: registry.npmmirror.com/yaml/1.10.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
|
410
src/App.vue
410
src/App.vue
|
@ -45,13 +45,13 @@ onMounted(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
|
const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
|
||||||
const options = ref<FormOptions[]>(
|
const options = ref<ComponentOptions[]>(
|
||||||
Array.from({ length: 1000 }).map((_, idx) => ({
|
Array.from({ length: 1000 }).map((_, idx) => ({
|
||||||
value: `Option ${idx + 1}`,
|
value: `Option ${idx + 1}`,
|
||||||
label: `${initials[idx % 10]}${idx}`
|
label: `${initials[idx % 10]}${idx}`
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
const options2 = ref<FormOptions[]>(
|
const options2 = ref<ComponentOptions[]>(
|
||||||
Array.from({ length: 10 }).map((_, idx) => {
|
Array.from({ length: 10 }).map((_, idx) => {
|
||||||
const label = idx + 1
|
const label = idx + 1
|
||||||
return {
|
return {
|
||||||
|
@ -65,7 +65,7 @@ const options2 = ref<FormOptions[]>(
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
const options3: FormOptions[] = [
|
const options3: ComponentOptions[] = [
|
||||||
{
|
{
|
||||||
value: 'guide',
|
value: 'guide',
|
||||||
label: 'Guide',
|
label: 'Guide',
|
||||||
|
@ -332,6 +332,20 @@ function generateData() {
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const holidays = [
|
||||||
|
'2021-10-01',
|
||||||
|
'2021-10-02',
|
||||||
|
'2021-10-03',
|
||||||
|
'2021-10-04',
|
||||||
|
'2021-10-05',
|
||||||
|
'2021-10-06',
|
||||||
|
'2021-10-07'
|
||||||
|
]
|
||||||
|
|
||||||
|
function isHoliday({ dayjs }) {
|
||||||
|
return holidays.includes(dayjs.format('YYYY-MM-DD'))
|
||||||
|
}
|
||||||
|
|
||||||
const schema = reactive<VFormSchema[]>([
|
const schema = reactive<VFormSchema[]>([
|
||||||
{
|
{
|
||||||
field: 'field1',
|
field: 'field1',
|
||||||
|
@ -438,99 +452,107 @@ const schema = reactive<VFormSchema[]>([
|
||||||
field: 'field14',
|
field: 'field14',
|
||||||
label: t('formDemo.default'),
|
label: t('formDemo.default'),
|
||||||
component: 'Select',
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '选项1',
|
label: 'option1',
|
||||||
value: '1'
|
value: '1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '选项2',
|
label: 'option2',
|
||||||
value: '2'
|
value: '2'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'field15',
|
field: 'field15',
|
||||||
label: t('formDemo.slot'),
|
label: t('formDemo.slot'),
|
||||||
component: 'Select',
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '选项1',
|
label: 'option1',
|
||||||
value: '1'
|
value: '1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '选项2',
|
label: 'option2',
|
||||||
value: '2'
|
value: '2'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
optionsSlot: true
|
optionsSlot: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'field16',
|
field: 'field16',
|
||||||
label: t('formDemo.group'),
|
label: t('formDemo.selectGroup'),
|
||||||
component: 'Select',
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '选项1',
|
label: 'option1',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '选项1-1',
|
label: 'option1-1',
|
||||||
value: '1-1'
|
value: '1-1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '选项1-2',
|
label: 'option1-2',
|
||||||
value: '1-2'
|
value: '1-2'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '选项2',
|
label: 'option2',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '选项2-1',
|
label: 'option2-1',
|
||||||
value: '2-1'
|
value: '2-1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '选项2-2',
|
label: 'option2-2',
|
||||||
value: '2-2'
|
value: '2-2'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'field17',
|
field: 'field17',
|
||||||
label: `${t('formDemo.group')}${t('formDemo.slot')}`,
|
label: `${t('formDemo.selectGroup')}${t('formDemo.slot')}`,
|
||||||
component: 'Select',
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '选项1',
|
label: 'option1',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '选项1-1',
|
label: 'option1-1',
|
||||||
value: '1-1'
|
value: '1-1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '选项1-2',
|
label: 'option1-2',
|
||||||
value: '1-2'
|
value: '1-2'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '选项2',
|
label: 'option2',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '选项2-1',
|
label: 'option2-1',
|
||||||
value: '2-1'
|
value: '2-1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '选项2-2',
|
label: 'option2-2',
|
||||||
value: '2-2'
|
value: '2-2'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
optionsSlot: true
|
optionsSlot: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'field18',
|
field: 'field18',
|
||||||
|
@ -541,14 +563,16 @@ const schema = reactive<VFormSchema[]>([
|
||||||
field: 'field19',
|
field: 'field19',
|
||||||
label: t('formDemo.default'),
|
label: t('formDemo.default'),
|
||||||
component: 'SelectV2',
|
component: 'SelectV2',
|
||||||
|
componentProps: {
|
||||||
options: options.value
|
options: options.value
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'field20',
|
field: 'field20',
|
||||||
label: t('formDemo.slot'),
|
label: t('formDemo.slot'),
|
||||||
component: 'SelectV2',
|
component: 'SelectV2',
|
||||||
options: options.value,
|
|
||||||
componentProps: {
|
componentProps: {
|
||||||
|
options: options.value,
|
||||||
slots: {
|
slots: {
|
||||||
default: true
|
default: true
|
||||||
}
|
}
|
||||||
|
@ -556,16 +580,18 @@ const schema = reactive<VFormSchema[]>([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'field21',
|
field: 'field21',
|
||||||
label: t('formDemo.group'),
|
label: t('formDemo.selectGroup'),
|
||||||
component: 'SelectV2',
|
component: 'SelectV2',
|
||||||
|
componentProps: {
|
||||||
options: options2.value
|
options: options2.value
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'field22',
|
field: 'field22',
|
||||||
label: `${t('formDemo.group')}${t('formDemo.slot')}`,
|
label: `${t('formDemo.selectGroup')}${t('formDemo.slot')}`,
|
||||||
component: 'SelectV2',
|
component: 'SelectV2',
|
||||||
options: options2.value,
|
|
||||||
componentProps: {
|
componentProps: {
|
||||||
|
options: options2.value,
|
||||||
slots: {
|
slots: {
|
||||||
default: true
|
default: true
|
||||||
}
|
}
|
||||||
|
@ -580,14 +606,16 @@ const schema = reactive<VFormSchema[]>([
|
||||||
field: 'field24',
|
field: 'field24',
|
||||||
label: t('formDemo.default'),
|
label: t('formDemo.default'),
|
||||||
component: 'Cascader',
|
component: 'Cascader',
|
||||||
|
componentProps: {
|
||||||
options: options3
|
options: options3
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'field25',
|
field: 'field25',
|
||||||
label: t('formDemo.slot'),
|
label: t('formDemo.slot'),
|
||||||
component: 'Cascader',
|
component: 'Cascader',
|
||||||
options: options3,
|
|
||||||
componentProps: {
|
componentProps: {
|
||||||
|
options: options3,
|
||||||
slots: {
|
slots: {
|
||||||
default: true
|
default: true
|
||||||
}
|
}
|
||||||
|
@ -710,15 +738,286 @@ const schema = reactive<VFormSchema[]>([
|
||||||
colProps: {
|
colProps: {
|
||||||
xl: 12
|
xl: 12
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field38',
|
||||||
|
label: t('formDemo.radio'),
|
||||||
|
component: 'Divider'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field39',
|
||||||
|
label: t('formDemo.default'),
|
||||||
|
component: 'Radio',
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'option-1',
|
||||||
|
value: '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'option-2',
|
||||||
|
value: '2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field40',
|
||||||
|
label: t('formDemo.button'),
|
||||||
|
component: 'RadioButton',
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'option-1',
|
||||||
|
value: '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'option-2',
|
||||||
|
value: '2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field41',
|
||||||
|
label: t('formDemo.checkbox'),
|
||||||
|
component: 'Divider'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field42',
|
||||||
|
label: t('formDemo.default'),
|
||||||
|
component: 'Checkbox',
|
||||||
|
value: [],
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'option-1',
|
||||||
|
value: '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'option-2',
|
||||||
|
value: '2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'option-3',
|
||||||
|
value: '23'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field43',
|
||||||
|
label: t('formDemo.button'),
|
||||||
|
component: 'CheckboxButton',
|
||||||
|
value: [],
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'option-1',
|
||||||
|
value: '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'option-2',
|
||||||
|
value: '2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'option-3',
|
||||||
|
value: '23'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field44',
|
||||||
|
component: 'Divider',
|
||||||
|
label: t('formDemo.slider')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field45',
|
||||||
|
component: 'Slider',
|
||||||
|
label: t('formDemo.default'),
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field46',
|
||||||
|
component: 'Divider',
|
||||||
|
label: t('formDemo.datePicker')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field47',
|
||||||
|
component: 'DatePicker',
|
||||||
|
label: t('formDemo.default'),
|
||||||
|
componentProps: {
|
||||||
|
type: 'date'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field48',
|
||||||
|
component: 'DatePicker',
|
||||||
|
label: t('formDemo.shortcuts'),
|
||||||
|
componentProps: {
|
||||||
|
type: 'date',
|
||||||
|
disabledDate: (time: Date) => {
|
||||||
|
return time.getTime() > Date.now()
|
||||||
|
},
|
||||||
|
shortcuts: [
|
||||||
|
{
|
||||||
|
text: t('formDemo.today'),
|
||||||
|
value: new Date()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: t('formDemo.yesterday'),
|
||||||
|
value: () => {
|
||||||
|
const date = new Date()
|
||||||
|
date.setTime(date.getTime() - 3600 * 1000 * 24)
|
||||||
|
return date
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: t('formDemo.aWeekAgo'),
|
||||||
|
value: () => {
|
||||||
|
const date = new Date()
|
||||||
|
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
|
||||||
|
return date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field49',
|
||||||
|
component: 'DatePicker',
|
||||||
|
label: t('formDemo.week'),
|
||||||
|
componentProps: {
|
||||||
|
type: 'week',
|
||||||
|
format: `[${t('formDemo.week')}] ww`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field50',
|
||||||
|
component: 'DatePicker',
|
||||||
|
label: t('formDemo.year'),
|
||||||
|
componentProps: {
|
||||||
|
type: 'year'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field51',
|
||||||
|
component: 'DatePicker',
|
||||||
|
label: t('formDemo.month'),
|
||||||
|
componentProps: {
|
||||||
|
type: 'month'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field52',
|
||||||
|
component: 'DatePicker',
|
||||||
|
label: t('formDemo.dates'),
|
||||||
|
componentProps: {
|
||||||
|
type: 'dates'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field53',
|
||||||
|
component: 'DatePicker',
|
||||||
|
label: t('formDemo.daterange'),
|
||||||
|
componentProps: {
|
||||||
|
type: 'daterange'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field54',
|
||||||
|
component: 'DatePicker',
|
||||||
|
label: t('formDemo.monthrange'),
|
||||||
|
componentProps: {
|
||||||
|
type: 'monthrange'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field55',
|
||||||
|
component: 'DatePicker',
|
||||||
|
label: t('formDemo.slot'),
|
||||||
|
componentProps: {
|
||||||
|
type: 'date',
|
||||||
|
format: 'YYYY/MM/DD',
|
||||||
|
valueFormat: 'YYYY-MM-DD',
|
||||||
|
slots: {
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field56',
|
||||||
|
component: 'Divider',
|
||||||
|
label: t('formDemo.dateTimePicker')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field57',
|
||||||
|
component: 'DatePicker',
|
||||||
|
label: t('formDemo.default'),
|
||||||
|
componentProps: {
|
||||||
|
type: 'datetime'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field58',
|
||||||
|
component: 'DatePicker',
|
||||||
|
label: t('formDemo.shortcuts'),
|
||||||
|
componentProps: {
|
||||||
|
type: 'datetime',
|
||||||
|
shortcuts: [
|
||||||
|
{
|
||||||
|
text: t('formDemo.today'),
|
||||||
|
value: new Date()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: t('formDemo.yesterday'),
|
||||||
|
value: () => {
|
||||||
|
const date = new Date()
|
||||||
|
date.setTime(date.getTime() - 3600 * 1000 * 24)
|
||||||
|
return date
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: t('formDemo.aWeekAgo'),
|
||||||
|
value: () => {
|
||||||
|
const date = new Date()
|
||||||
|
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
|
||||||
|
return date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field59',
|
||||||
|
component: 'DatePicker',
|
||||||
|
label: t('formDemo.dateTimerange'),
|
||||||
|
componentProps: {
|
||||||
|
type: 'datetimerange'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field60',
|
||||||
|
component: 'Divider',
|
||||||
|
label: t('formDemo.timePicker')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field61',
|
||||||
|
component: 'TimePicker',
|
||||||
|
label: t('formDemo.default')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field62',
|
||||||
|
component: 'Divider',
|
||||||
|
label: t('formDemo.timeSelect')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field63',
|
||||||
|
component: 'TimeSelect',
|
||||||
|
label: t('formDemo.default')
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
if (schema[2].componentProps) {
|
|
||||||
schema[2].componentProps.placeholder = 'test'
|
|
||||||
console.log(schema[2])
|
|
||||||
}
|
|
||||||
}, 3000)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -775,6 +1074,51 @@ setTimeout(() => {
|
||||||
<template #field36-default="{ option }">
|
<template #field36-default="{ option }">
|
||||||
<span>{{ option.value }} - {{ option.desc }}</span>
|
<span>{{ option.value }} - {{ option.desc }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #field55-default="cell">
|
||||||
|
<div class="cell" :class="{ current: cell.isCurrent }">
|
||||||
|
<span class="text">{{ cell.text }}</span>
|
||||||
|
<span v-if="isHoliday(cell)" class="holiday"></span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</VFrom>
|
</VFrom>
|
||||||
</ElConfigProvider>
|
</ElConfigProvider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.cell {
|
||||||
|
height: 30px;
|
||||||
|
padding: 3px 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
display: block;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
margin: 0 auto;
|
||||||
|
line-height: 24px;
|
||||||
|
border-radius: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.current {
|
||||||
|
.text {
|
||||||
|
color: #fff;
|
||||||
|
background: purple;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.holiday {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0px;
|
||||||
|
left: 50%;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
background: red;
|
||||||
|
border-radius: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -12,6 +12,8 @@ import {
|
||||||
setModel
|
setModel
|
||||||
} from './helper'
|
} from './helper'
|
||||||
import { useRenderSelect } from './components/useRenderSelect'
|
import { useRenderSelect } from './components/useRenderSelect'
|
||||||
|
import { useRenderRadio } from './components/useRenderRadio'
|
||||||
|
import { useRenderChcekbox } from './components/useRenderChcekbox'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'VForm',
|
name: 'VForm',
|
||||||
|
@ -93,7 +95,11 @@ export default defineComponent({
|
||||||
const slotsMap: Recordable = {
|
const slotsMap: Recordable = {
|
||||||
...setItemComponentSlots(slots, item?.componentProps?.slots, item.field)
|
...setItemComponentSlots(slots, item?.componentProps?.slots, item.field)
|
||||||
}
|
}
|
||||||
if (item?.component !== 'SelectV2' && item.options) {
|
if (
|
||||||
|
item?.component !== 'SelectV2' &&
|
||||||
|
item?.component !== 'Cascader' &&
|
||||||
|
item?.componentProps?.options
|
||||||
|
) {
|
||||||
slotsMap.default = () => renderOptions(item)
|
slotsMap.default = () => renderOptions(item)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -105,8 +111,9 @@ export default defineComponent({
|
||||||
vModel={formModel[item.field]}
|
vModel={formModel[item.field]}
|
||||||
{...(autoSetPlaceholder && setTextPlaceholder(item))}
|
{...(autoSetPlaceholder && setTextPlaceholder(item))}
|
||||||
{...setComponentProps(item)}
|
{...setComponentProps(item)}
|
||||||
{...(notRenderOptions.includes(item?.component as string) && item.options
|
{...(notRenderOptions.includes(item?.component as string) &&
|
||||||
? { options: item.options || [] }
|
item?.componentProps?.options
|
||||||
|
? { options: item?.componentProps?.options || [] }
|
||||||
: {})}
|
: {})}
|
||||||
>
|
>
|
||||||
{{ ...slotsMap }}
|
{{ ...slotsMap }}
|
||||||
|
@ -123,6 +130,14 @@ export default defineComponent({
|
||||||
case 'Select':
|
case 'Select':
|
||||||
const { renderSelectOptions } = useRenderSelect(slots)
|
const { renderSelectOptions } = useRenderSelect(slots)
|
||||||
return renderSelectOptions(item)
|
return renderSelectOptions(item)
|
||||||
|
case 'Radio':
|
||||||
|
case 'RadioButton':
|
||||||
|
const { renderRadioOptions } = useRenderRadio()
|
||||||
|
return renderRadioOptions(item)
|
||||||
|
case 'Checkbox':
|
||||||
|
case 'CheckboxButton':
|
||||||
|
const { renderChcekboxOptions } = useRenderChcekbox()
|
||||||
|
return renderChcekboxOptions(item)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -142,7 +157,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<ElForm ref={formRef} {...getFormBindValue()} model={formModel}>
|
<ElForm ref={formRef} {...getFormBindValue()} model={formModel} class="v-form">
|
||||||
{{
|
{{
|
||||||
// 如果需要自定义,就什么都不渲染,而是提供默认插槽
|
// 如果需要自定义,就什么都不渲染,而是提供默认插槽
|
||||||
default: () => (isCustom ? getSlot(slots, 'default') : renderWrap())
|
default: () => (isCustom ? getSlot(slots, 'default') : renderWrap())
|
||||||
|
|
|
@ -22,6 +22,7 @@ import {
|
||||||
const componentMap: Recordable<Component, ComponentName> = {
|
const componentMap: Recordable<Component, ComponentName> = {
|
||||||
Radio: ElRadioGroup,
|
Radio: ElRadioGroup,
|
||||||
Checkbox: ElCheckboxGroup,
|
Checkbox: ElCheckboxGroup,
|
||||||
|
CheckboxButton: ElCheckboxGroup,
|
||||||
Input: ElInput,
|
Input: ElInput,
|
||||||
Autocomplete: ElAutocomplete,
|
Autocomplete: ElAutocomplete,
|
||||||
InputNumber: ElInputNumber,
|
InputNumber: ElInputNumber,
|
||||||
|
@ -36,7 +37,8 @@ const componentMap: Recordable<Component, ComponentName> = {
|
||||||
Transfer: ElTransfer,
|
Transfer: ElTransfer,
|
||||||
Divider: ElDivider,
|
Divider: ElDivider,
|
||||||
TimeSelect: ElTimeSelect,
|
TimeSelect: ElTimeSelect,
|
||||||
SelectV2: ElSelectV2
|
SelectV2: ElSelectV2,
|
||||||
|
RadioButton: ElRadioGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
export { componentMap }
|
export { componentMap }
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { ElCheckbox, ElCheckboxButton } from 'element-plus'
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
|
export function useRenderChcekbox() {
|
||||||
|
function renderChcekboxOptions(item: VFormSchema) {
|
||||||
|
// 如果有别名,就取别名
|
||||||
|
const labelAlias = item?.componentProps?.optionsAlias?.labelField
|
||||||
|
const valueAlias = item?.componentProps?.optionsAlias?.valueField
|
||||||
|
const Com = (item.component === 'Checkbox' ? ElCheckbox : ElCheckboxButton) as ReturnType<
|
||||||
|
typeof defineComponent
|
||||||
|
>
|
||||||
|
return item?.componentProps?.options?.map((option) => {
|
||||||
|
return <Com label={option[labelAlias || 'value']}>{option[valueAlias || 'label']}</Com>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
renderChcekboxOptions
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { ElRadio, ElRadioButton } from 'element-plus'
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
|
export function useRenderRadio() {
|
||||||
|
function renderRadioOptions(item: VFormSchema) {
|
||||||
|
// 如果有别名,就取别名
|
||||||
|
const labelAlias = item?.componentProps?.optionsAlias?.labelField
|
||||||
|
const valueAlias = item?.componentProps?.optionsAlias?.valueField
|
||||||
|
const Com = (item.component === 'Radio' ? ElRadio : ElRadioButton) as ReturnType<
|
||||||
|
typeof defineComponent
|
||||||
|
>
|
||||||
|
return item?.componentProps?.options?.map((option) => {
|
||||||
|
return <Com label={option[labelAlias || 'value']}>{option[valueAlias || 'label']}</Com>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
renderRadioOptions
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,11 +6,11 @@ export function useRenderSelect(slots: Slots) {
|
||||||
// 渲染 select options
|
// 渲染 select options
|
||||||
function renderSelectOptions(item: VFormSchema) {
|
function renderSelectOptions(item: VFormSchema) {
|
||||||
// 如果有别名,就取别名
|
// 如果有别名,就取别名
|
||||||
const labelAlias = item.optionsField?.labelField
|
const labelAlias = item?.componentProps?.optionsAlias?.labelField
|
||||||
return item.options?.map((option) => {
|
return item?.componentProps?.options?.map((option) => {
|
||||||
if (option?.options?.length) {
|
if (option?.options?.length) {
|
||||||
return (
|
return (
|
||||||
<ElOptionGroup label={labelAlias ? option[labelAlias] : option['label']}>
|
<ElOptionGroup label={option[labelAlias || 'label']}>
|
||||||
{() => {
|
{() => {
|
||||||
return option?.options?.map((v) => {
|
return option?.options?.map((v) => {
|
||||||
return renderSelectOptionItem(item, v)
|
return renderSelectOptionItem(item, v)
|
||||||
|
@ -25,19 +25,18 @@ export function useRenderSelect(slots: Slots) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 渲染 select option item
|
// 渲染 select option item
|
||||||
function renderSelectOptionItem(item: VFormSchema, option: FormOptions) {
|
function renderSelectOptionItem(item: VFormSchema, option: ComponentOptions) {
|
||||||
// 如果有别名,就取别名
|
// 如果有别名,就取别名
|
||||||
const labelAlias = item.optionsField?.labelField
|
const labelAlias = item?.componentProps?.optionsAlias?.labelField
|
||||||
const valueAlias = item.optionsField?.valueField
|
const valueAlias = item?.componentProps?.optionsAlias?.valueField
|
||||||
return (
|
return (
|
||||||
<ElOption
|
<ElOption label={option[labelAlias || 'label']} value={option[valueAlias || 'value']}>
|
||||||
label={labelAlias ? option[labelAlias] : option['label']}
|
|
||||||
value={valueAlias ? option[valueAlias] : option['value']}
|
|
||||||
>
|
|
||||||
{{
|
{{
|
||||||
default: () =>
|
default: () =>
|
||||||
// option 插槽名规则,{field}-option
|
// option 插槽名规则,{field}-option
|
||||||
item.optionsSlot ? getSlot(slots, `${item.field}-option`, { item: option }) : undefined
|
item?.componentProps?.optionsSlot
|
||||||
|
? getSlot(slots, `${item.field}-option`, { item: option })
|
||||||
|
: undefined
|
||||||
}}
|
}}
|
||||||
</ElOption>
|
</ElOption>
|
||||||
)
|
)
|
||||||
|
|
|
@ -16,13 +16,32 @@ export default {
|
||||||
position: 'Position',
|
position: 'Position',
|
||||||
autocomplete: 'Autocomplete',
|
autocomplete: 'Autocomplete',
|
||||||
select: 'Select',
|
select: 'Select',
|
||||||
group: 'Select Group',
|
selectGroup: 'Select Group',
|
||||||
selectV2: 'SelectV2',
|
selectV2: 'SelectV2',
|
||||||
cascader: 'Cascader',
|
cascader: 'Cascader',
|
||||||
switch: 'Switch',
|
switch: 'Switch',
|
||||||
rate: 'Rate',
|
rate: 'Rate',
|
||||||
colorPicker: 'ColorPicker',
|
colorPicker: 'Color Picker',
|
||||||
transfer: 'Transfer',
|
transfer: 'Transfer',
|
||||||
render: 'Render'
|
render: 'Render',
|
||||||
|
radio: 'Radio',
|
||||||
|
button: 'Button',
|
||||||
|
checkbox: 'Checkbox',
|
||||||
|
slider: 'Slider',
|
||||||
|
datePicker: 'Date Picker',
|
||||||
|
shortcuts: 'Shortcuts',
|
||||||
|
today: 'Today',
|
||||||
|
yesterday: 'Yesterday',
|
||||||
|
aWeekAgo: 'A week ago',
|
||||||
|
week: 'Week',
|
||||||
|
year: 'Year',
|
||||||
|
month: 'Month',
|
||||||
|
dates: 'Dates',
|
||||||
|
daterange: 'Date Range',
|
||||||
|
monthrange: 'Month Range',
|
||||||
|
dateTimePicker: 'DateTimePicker',
|
||||||
|
dateTimerange: 'Datetime Range',
|
||||||
|
timePicker: 'Time Picker',
|
||||||
|
timeSelect: 'Time Select'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,32 @@ export default {
|
||||||
position: '位置',
|
position: '位置',
|
||||||
autocomplete: '自动补全',
|
autocomplete: '自动补全',
|
||||||
select: '选择器',
|
select: '选择器',
|
||||||
group: '选项分组',
|
selectGroup: '选项分组',
|
||||||
selectV2: '虚拟列表选择器',
|
selectV2: '虚拟列表选择器',
|
||||||
cascader: '级联选择器',
|
cascader: '级联选择器',
|
||||||
switch: '开关',
|
switch: '开关',
|
||||||
rate: '评分',
|
rate: '评分',
|
||||||
colorPicker: '颜色选择器',
|
colorPicker: '颜色选择器',
|
||||||
transfer: '穿梭框',
|
transfer: '穿梭框',
|
||||||
render: '渲染器'
|
render: '渲染器',
|
||||||
|
radio: '单选框',
|
||||||
|
button: '按钮',
|
||||||
|
checkbox: '多选框',
|
||||||
|
slider: '滑块',
|
||||||
|
datePicker: '日期选择器',
|
||||||
|
shortcuts: '快捷选项',
|
||||||
|
today: '今天',
|
||||||
|
yesterday: '昨天',
|
||||||
|
aWeekAgo: '一周前',
|
||||||
|
week: '周',
|
||||||
|
year: '年',
|
||||||
|
month: '月',
|
||||||
|
dates: '日期',
|
||||||
|
daterange: '日期范围',
|
||||||
|
monthrange: '月份范围',
|
||||||
|
dateTimePicker: '日期时间选择器',
|
||||||
|
dateTimerange: '日期时间范围',
|
||||||
|
timePicker: '时间选择器',
|
||||||
|
timeSelect: '时间选择'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@ declare global {
|
||||||
// BfForm types start
|
// BfForm types start
|
||||||
declare type ComponentName =
|
declare type ComponentName =
|
||||||
| 'Radio'
|
| 'Radio'
|
||||||
|
| 'RadioButton'
|
||||||
| 'Checkbox'
|
| 'Checkbox'
|
||||||
|
| 'CheckboxButton'
|
||||||
| 'Input'
|
| 'Input'
|
||||||
| 'Autocomplete'
|
| 'Autocomplete'
|
||||||
| 'InputNumber'
|
| 'InputNumber'
|
||||||
|
@ -52,21 +54,26 @@ declare global {
|
||||||
style?: CSSProperties
|
style?: CSSProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
declare type FormOptions = {
|
declare type ComponentOptions = {
|
||||||
label?: string
|
label?: string
|
||||||
value?: FormValueTypes
|
value?: FormValueTypes
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
key?: string | number
|
key?: string | number
|
||||||
children?: FormOptions[]
|
children?: ComponentOptions[]
|
||||||
options?: FormOptions[]
|
options?: ComponentOptions[]
|
||||||
[key: string]: any
|
} & Recordable
|
||||||
}
|
|
||||||
|
|
||||||
declare type FormOptionsAlias = {
|
declare type ComponentOptionsAlias = {
|
||||||
labelField?: string
|
labelField?: string
|
||||||
valueField?: string
|
valueField?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare type ComponentProps = {
|
||||||
|
optionsAlias?: ComponentOptionsAlias
|
||||||
|
options?: ComponentOptions[]
|
||||||
|
optionsSlot?: boolean
|
||||||
|
} & Recordable
|
||||||
|
|
||||||
declare type VFormSchema = {
|
declare type VFormSchema = {
|
||||||
// 唯一值
|
// 唯一值
|
||||||
field: string
|
field: string
|
||||||
|
@ -75,23 +82,15 @@ declare global {
|
||||||
// col组件属性
|
// col组件属性
|
||||||
colProps?: ColProps
|
colProps?: ColProps
|
||||||
// 表单组件属性,slots对应的是表单组件的插槽,规则:${field}-xxx,具体可以查看element-plus文档
|
// 表单组件属性,slots对应的是表单组件的插槽,规则:${field}-xxx,具体可以查看element-plus文档
|
||||||
componentProps?: { slots?: Recordable } & Recordable
|
componentProps?: { slots?: Recordable } & ComponentProps
|
||||||
// formItem组件属性
|
// formItem组件属性
|
||||||
formItemProps?: FormItemProps
|
formItemProps?: FormItemProps
|
||||||
// 渲染的组件
|
// 渲染的组件
|
||||||
component?: ComponentName
|
component?: ComponentName
|
||||||
// 初始值
|
// 初始值
|
||||||
value?: FormValueTypes
|
value?: FormValueTypes
|
||||||
// 下拉选项
|
|
||||||
options?: FormOptions[]
|
|
||||||
// 下拉选项别名
|
|
||||||
optionsField?: FormOptionsAlias
|
|
||||||
// 下拉选项插槽,规则:${field}-option
|
|
||||||
optionsSlot?: boolean
|
|
||||||
// 是否隐藏
|
// 是否隐藏
|
||||||
hidden?: boolean
|
hidden?: boolean
|
||||||
// 表单组件插槽,规则:${field}
|
|
||||||
slot?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// VForm types end
|
// VForm types end
|
||||||
|
|
Loading…
Reference in New Issue