173 lines
6.8 KiB
Vue
173 lines
6.8 KiB
Vue
<template>
|
|
<a-form ref="formProMaxRef" v-bind="props" :model="modelValue">
|
|
<a-row :gutter="props.gutter">
|
|
<a-col v-for="(item,field) in props.formItemOptions as FormProMaxItemOptions<T>" :key="field" v-bind="getResponsive(item)">
|
|
<a-form-item :name="field" v-bind="item" :label="undefined">
|
|
<template v-slot:label>
|
|
{{ item.label }}
|
|
<template v-if="item.remarkRender">
|
|
<a-popover :title="item.label" :content="item.remarkRender()">
|
|
<QuestionCircleOutlined class="margin-left-xs" style="color: red" />
|
|
</a-popover>
|
|
</template>
|
|
</template>
|
|
<!-- 自定义组件 -->
|
|
<!-- ant design vue 组件 -->
|
|
<a-input
|
|
v-if="item.type === 'input'"
|
|
v-model:value="modelValue[field]"
|
|
style="width: 100%"
|
|
v-bind="item.componentsProps"
|
|
:placeholder="getPlaceholder(item)"
|
|
:allowClear="item.componentsProps?.allowClear ?? true"
|
|
/>
|
|
<a-input-password
|
|
v-else-if="item.type === 'inputPassword'"
|
|
v-model:value="modelValue[field]"
|
|
style="width: 100%"
|
|
v-bind="item.componentsProps"
|
|
:placeholder="getPlaceholder(item)"
|
|
:allowClear="item.componentsProps?.allowClear ?? true"
|
|
/>
|
|
<a-input-number v-else-if="item.type === 'inputNumber'" v-model:value="modelValue[field]" style="width: 100%" v-bind="item.componentsProps" :placeholder="getPlaceholder(item)" />
|
|
<a-textarea
|
|
v-else-if="item.type === 'inputTextArea'"
|
|
v-model:value="modelValue[field]"
|
|
style="width: 100%"
|
|
v-bind="item.componentsProps"
|
|
:placeholder="getPlaceholder(item)"
|
|
:allowClear="item.componentsProps?.allowClear ?? true"
|
|
/>
|
|
<a-radio-group v-else-if="item.type === 'radioGroup'" v-model:value="modelValue[field]" style="width: 100%" v-bind="item.componentsProps" :options="item.options" />
|
|
<a-checkbox-group v-else-if="item.type === 'checkboxGroup'" v-model:value="modelValue[field]" style="width: 100%" v-bind="item.componentsProps" :options="item.options" />
|
|
<a-select
|
|
v-else-if="item.type === 'select'"
|
|
v-model:value="modelValue[field]"
|
|
style="width: 100%"
|
|
v-bind="item.componentsProps"
|
|
:placeholder="getPlaceholder(item)"
|
|
:allowClear="item.componentsProps?.allowClear ?? true"
|
|
:options="item.options"
|
|
/>
|
|
<a-tree-select
|
|
v-else-if="item.type === 'treeSelect'"
|
|
style="width: 100%"
|
|
v-model:value="modelValue[field]"
|
|
v-bind="item.componentsProps"
|
|
:placeholder="getPlaceholder(item)"
|
|
:allowClear="item.componentsProps?.allowClear ?? true"
|
|
:tree-data="item.options"
|
|
/>
|
|
<a-cascader
|
|
v-else-if="item.type === 'cascader'"
|
|
style="width: 100%"
|
|
v-model:value="modelValue[field]"
|
|
v-bind="item.componentsProps"
|
|
:placeholder="getPlaceholder(item)"
|
|
:allowClear="item.componentsProps?.allowClear ?? true"
|
|
:options="item.options"
|
|
/>
|
|
<a-range-picker
|
|
v-else-if="item.type === 'rangePicker'"
|
|
style="width: 100%"
|
|
v-model:value="modelValue[field]"
|
|
v-bind="item.componentsProps"
|
|
:placeholder="item.componentsProps?.placeholder ?? ['开始日期', '结束日期']"
|
|
:allowClear="item.componentsProps?.allowClear ?? true"
|
|
/>
|
|
<a-date-picker
|
|
v-else-if="item.type === 'datePicker'"
|
|
style="width: 100%"
|
|
v-model:value="modelValue[field]"
|
|
v-bind="item.componentsProps"
|
|
:placeholder="item.componentsProps?.placeholder ?? '请选择日期'"
|
|
:allowClear="item.componentsProps?.allowClear ?? true"
|
|
/>
|
|
<a-time-range-picker
|
|
v-else-if="item.type === 'timeRangePicker'"
|
|
style="width: 100%"
|
|
v-model:value="modelValue[field]"
|
|
v-bind="item.componentsProps"
|
|
:placeholder="item.componentsProps?.placeholder ?? ['开始时间', '结束时间']"
|
|
:allowClear="item.componentsProps?.allowClear ?? true"
|
|
/>
|
|
<a-time-picker
|
|
v-else-if="item.type === 'timePicker'"
|
|
style="width: 100%"
|
|
v-model:value="modelValue[field]"
|
|
v-bind="item.componentsProps"
|
|
:placeholder="getPlaceholder(item)"
|
|
:allowClear="item.componentsProps?.allowClear ?? true"
|
|
/>
|
|
<template v-else-if="item.type === 'custom'">
|
|
<component :is="item.customRender" />
|
|
</template>
|
|
</a-form-item>
|
|
</a-col>
|
|
</a-row>
|
|
<slot name="formOperation"></slot>
|
|
</a-form>
|
|
</template>
|
|
|
|
<script setup lang="ts" generic="T extends Record<string,any>">
|
|
import { FormInstance } from 'ant-design-vue'
|
|
import { ref } from 'vue'
|
|
import { FormExpose } from 'ant-design-vue/es/form/Form'
|
|
import { QuestionCircleOutlined } from '@ant-design/icons-vue'
|
|
import { FormProMaxItemOptions, FormProMaxItemProps, FormProMaxProps } from '@/types/components/form/index.ts'
|
|
|
|
const modelValue = defineModel<T>('value', {
|
|
default: {},
|
|
})
|
|
|
|
const props = withDefaults(defineProps<FormProMaxProps<T>>(), {
|
|
grid: () => {
|
|
return {
|
|
span: 24,
|
|
}
|
|
},
|
|
gutter: 10,
|
|
labelCol: () => {
|
|
return {
|
|
style: {
|
|
width: '100px',
|
|
},
|
|
}
|
|
},
|
|
wrapperCol: () => {
|
|
return {
|
|
span: 18,
|
|
}
|
|
},
|
|
labelAlign: 'left',
|
|
colon: undefined,
|
|
disabled: undefined,
|
|
hideRequiredMark: undefined,
|
|
labelWrap: undefined,
|
|
scrollToFirstError: undefined,
|
|
validateOnRuleChange: undefined,
|
|
})
|
|
console.log(props)
|
|
const formProMaxRef = ref<FormInstance>(null!)
|
|
|
|
const getResponsive = (item: FormProMaxItemProps): Grid => {
|
|
//span优先级高于响应式设置
|
|
if (item.grid) return item.grid.span ? { span: item.grid.span } : { ...item.grid }
|
|
return { ...props.grid }
|
|
}
|
|
|
|
//优先级: 组件本身=》formItem=》label
|
|
const getPlaceholder = (item: FormProMaxItemProps) => item.componentsProps?.placeholder ?? item.placeholder ?? (item.type.includes('input') ? `请输入${item.label}` : `请选择${item.label}`)
|
|
|
|
defineExpose<FormExpose>({
|
|
validate: (nameList, options) => formProMaxRef.value?.validate(nameList, options),
|
|
resetFields: (name) => formProMaxRef.value?.resetFields(name),
|
|
clearValidate: () => formProMaxRef.value?.clearValidate(),
|
|
getFieldsValue: (nameList) => formProMaxRef.value?.getFieldsValue(nameList),
|
|
scrollToField: (name, options) => formProMaxRef.value?.scrollToField(name, options),
|
|
validateFields: (nameList, options) => formProMaxRef.value?.validateFields(nameList, options),
|
|
})
|
|
</script>
|
|
|
|
<style scoped></style>
|