|
|
@@ -1,24 +1,37 @@
|
|
|
<template>
|
|
|
<div class="form">
|
|
|
- <a-form ref="formRef" :model="props.formData" v-bind="props.formExtraProps" layout="vertical" :id="props.formId" :validateTrigger="['submit']" >
|
|
|
- <a-row v-for="(key, index) in Object.keys(newFormTemp)" :key="index" :id="key">
|
|
|
+ <a-form ref="formRef" :model="props.formData" v-bind="props.formExtraProps" layout="vertical" :id="props.formId"
|
|
|
+ :validateTrigger="['submit']">
|
|
|
+ <a-row v-for="(key, index) in Object.keys(newFormTemp)" :key="index" :id="key" :gutter="16">
|
|
|
<a-col :span="24" v-if="formGroups.length > 0">
|
|
|
- <div class="group-title">{{ formGroups.find((v) => v.id === key)?.name }}</div>
|
|
|
+ <BsCatalog :title="formGroups.find((v) => v.id === key)?.name"
|
|
|
+ v-if="formGroups.findIndex((item) => item.type === 'dot') > -1" />
|
|
|
+ <div class="group-title" v-else>{{formGroups.find((v) => v.id === key)?.name}}</div>
|
|
|
</a-col>
|
|
|
- <a-col :span="24" v-for="(item, idx) in newFormTemp[key]">
|
|
|
- <a-row>
|
|
|
- <a-col :span="24" v-if="item.visible === DISPLAY_STATE.VISIBLE">
|
|
|
- <a-form-item :label="item.label" :name="item.field" :required="item.required === REQUIRED_STATE.REQUIRED" v-bind="item.formItemExtraProps">
|
|
|
- <component
|
|
|
- :is="item.component"
|
|
|
- v-model:value="props.formData[item.field]"
|
|
|
- v-model:checked="props.formData[item.field]"
|
|
|
- v-bind="item.componentProps"
|
|
|
- @change="handleFieldChange(item, $event)"
|
|
|
- />
|
|
|
- </a-form-item>
|
|
|
- </a-col>
|
|
|
- </a-row>
|
|
|
+ <a-col :span="item.span ?? 24" v-for="(item, idx) in newFormTemp[key]">
|
|
|
+ <a-form-item v-if="item.visible === DISPLAY_STATE.VISIBLE" :name="item.field"
|
|
|
+ :required="item.required === REQUIRED_STATE.REQUIRED" :label="item.label" v-bind="item.formItemExtraProps">
|
|
|
+
|
|
|
+ <template #label v-if="item.tooltip">
|
|
|
+ {{ item.label }}
|
|
|
+ <a-tooltip class="tooltip">
|
|
|
+ <template #title>
|
|
|
+ <span>{{ item.tooltip }}</span>
|
|
|
+ </template>
|
|
|
+ <QuestionCircleOutlined />
|
|
|
+ </a-tooltip>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #label v-else>{{ item.label }}</template>
|
|
|
+ <component :is="item.component" v-model:value="props.formData[item.field]"
|
|
|
+ v-model:checked="props.formData[item.field]" v-bind="item.componentProps"
|
|
|
+ @change="handleFieldChange(item, $event)">
|
|
|
+ <slot>{{ item.componentProps?.buttonText || '' }}</slot>
|
|
|
+ <template v-for="slot in item.componentProps.slots" #[slot.slotName]>
|
|
|
+ <component :is="slot.customRender()" v-bind="slot.slotProps"></component>
|
|
|
+ </template>
|
|
|
+ </component>
|
|
|
+ </a-form-item>
|
|
|
</a-col>
|
|
|
|
|
|
<a-col :span="24" v-if="!footerRender && !slots.footerRender">
|
|
|
@@ -45,111 +58,128 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="jsx">
|
|
|
- import { computed, ref, useSlots } from 'vue';
|
|
|
- import RenderVNode from '/@/components/BsUi/RenderVNode/index.js';
|
|
|
- import { groupBy, mapValues, sortBy } from 'lodash';
|
|
|
- import { DISPLAY_STATE, REQUIRED_STATE } from '/@/components/BsUi/constant.js'
|
|
|
-
|
|
|
- const formRef = ref(null);
|
|
|
- const confirmLoading = ref(false);
|
|
|
-
|
|
|
- const props = defineProps({
|
|
|
- formFields: {
|
|
|
- required: true,
|
|
|
- default: [],
|
|
|
- },
|
|
|
- formData: {
|
|
|
- required: true,
|
|
|
- default: {},
|
|
|
- },
|
|
|
- formExtraProps: {
|
|
|
- required: false,
|
|
|
- default: null,
|
|
|
- },
|
|
|
- footerRender: {
|
|
|
- required: false,
|
|
|
- default: null,
|
|
|
- },
|
|
|
- formGroups: {
|
|
|
- required: false,
|
|
|
- default: [],
|
|
|
- },
|
|
|
- formId: {
|
|
|
- required: false,
|
|
|
- default: 'AchorContentId',
|
|
|
- },
|
|
|
- isShowGroupTitle: {
|
|
|
- required: false,
|
|
|
- default: true,
|
|
|
- },
|
|
|
- });
|
|
|
- const emits = defineEmits(['cancel', 'ok', 'change']);
|
|
|
- const slots = useSlots();
|
|
|
+import { computed, ref, useSlots } from 'vue';
|
|
|
+import RenderVNode from '/@/components/BsUi/RenderVNode/index.js';
|
|
|
+import { groupBy, mapValues, sortBy } from 'lodash';
|
|
|
+import { DISPLAY_STATE, REQUIRED_STATE } from '/@/components/BsUi/constant.js'
|
|
|
+import BsCatalog from '/@/components/BsUi/Catalog/index.vue';
|
|
|
+const formRef = ref(null);
|
|
|
+const confirmLoading = ref(false);
|
|
|
|
|
|
- const handleFieldChange = (field, value) => {
|
|
|
- formRef.value.validateFields([field.field])
|
|
|
- field?.onChange && field?.onChange(value)
|
|
|
- emits('change', value)
|
|
|
- }
|
|
|
+const props = defineProps({
|
|
|
+ formFields: {
|
|
|
+ required: true,
|
|
|
+ default: [],
|
|
|
+ },
|
|
|
+ formData: {
|
|
|
+ required: true,
|
|
|
+ default: {},
|
|
|
+ },
|
|
|
+ formExtraProps: {
|
|
|
+ required: false,
|
|
|
+ default: null,
|
|
|
+ },
|
|
|
+ footerRender: {
|
|
|
+ required: false,
|
|
|
+ default: null,
|
|
|
+ },
|
|
|
+ formGroups: {
|
|
|
+ required: false,
|
|
|
+ default: [],
|
|
|
+ },
|
|
|
+ formId: {
|
|
|
+ required: false,
|
|
|
+ default: 'AchorContentId',
|
|
|
+ },
|
|
|
+ isShowGroupTitle: {
|
|
|
+ required: false,
|
|
|
+ default: true,
|
|
|
+ },
|
|
|
+});
|
|
|
+const emits = defineEmits(['cancel', 'ok', 'change']);
|
|
|
+const slots = useSlots();
|
|
|
+
|
|
|
+const handleFieldChange = (field, value) => {
|
|
|
+ formRef.value.validateFields([field.field])
|
|
|
+ field?.onChange && field?.onChange(value)
|
|
|
+ emits('change', value)
|
|
|
+}
|
|
|
+
|
|
|
+const ValidatorSingalField =(field)=>{
|
|
|
+ return new Promise((resolve,reject)=>{
|
|
|
+ formRef.value.validateFields([field])
|
|
|
+ .then((res)=>{
|
|
|
+ resolve(res)
|
|
|
+ })
|
|
|
+ .catch((error)=>{
|
|
|
+ reject(error)
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const handlerFormValidator = () => {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ formRef.value
|
|
|
+ .validateFields()
|
|
|
+ .then(() => {
|
|
|
+ resolve();
|
|
|
+ })
|
|
|
+ .catch((error) => {
|
|
|
+ reject(error);
|
|
|
+ });
|
|
|
+ });
|
|
|
+};
|
|
|
|
|
|
+const cancelHandle = () => {
|
|
|
+ emits('cancel');
|
|
|
+};
|
|
|
+const setLoading = (loading) => {
|
|
|
+ confirmLoading.value = loading;
|
|
|
+};
|
|
|
|
|
|
- const handlerFormValidator = () => {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- formRef.value
|
|
|
- .validateFields()
|
|
|
- .then(() => {
|
|
|
- resolve();
|
|
|
- })
|
|
|
- .catch((error) => {
|
|
|
- reject(error);
|
|
|
- });
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
- const cancelHandle = () => {
|
|
|
- emits('cancel');
|
|
|
- };
|
|
|
- const setLoading = (loading) => {
|
|
|
- confirmLoading.value = loading;
|
|
|
- };
|
|
|
-
|
|
|
- const confirmHandle = () => {
|
|
|
- handlerFormValidator.then((res) => {
|
|
|
- emits('ok', props.formData, formRef.value, setLoading);
|
|
|
- });
|
|
|
- };
|
|
|
-
|
|
|
- const newFormTemp = computed(() => {
|
|
|
- const groupByIds = groupBy(props.formFields, 'groupId');
|
|
|
- return mapValues(groupByIds, (group) => sortBy(group, 'sort'));
|
|
|
+const confirmHandle = () => {
|
|
|
+ handlerFormValidator.then((res) => {
|
|
|
+ emits('ok', props.formData, formRef.value, setLoading);
|
|
|
});
|
|
|
+};
|
|
|
|
|
|
- defineExpose({ handlerFormValidator })
|
|
|
+const newFormTemp = computed(() => {
|
|
|
+ const groupByIds = groupBy(props.formFields, 'groupId');
|
|
|
+ return mapValues(groupByIds, (group) => sortBy(group, 'sort'));
|
|
|
+});
|
|
|
+
|
|
|
+defineExpose({ handlerFormValidator ,ValidatorSingalField})
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
- .form {
|
|
|
+.form {
|
|
|
+ width: 100%;
|
|
|
+
|
|
|
+ :deep(.ant-form-item) {
|
|
|
+ margin: 10px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .group-title {
|
|
|
width: 100%;
|
|
|
- :deep(.ant-form-item) {
|
|
|
- margin: 10px 0;
|
|
|
- }
|
|
|
+ height: 40px;
|
|
|
+ background: #e0e8f5;
|
|
|
+ line-height: 40px;
|
|
|
+ color: #4285f4;
|
|
|
+ font-size: 16px;
|
|
|
+ padding-left: 15px;
|
|
|
|
|
|
- .group-title {
|
|
|
- width: 100%;
|
|
|
- height: 40px;
|
|
|
- background: #e0e8f5;
|
|
|
- line-height: 40px;
|
|
|
- color: #4285f4;
|
|
|
- font-size: 16px;
|
|
|
- padding-left: 15px;
|
|
|
- &::before {
|
|
|
- content: '';
|
|
|
- width: 2px;
|
|
|
- height: 100%;
|
|
|
- position: absolute;
|
|
|
- left: 0;
|
|
|
- background: #4285f4;
|
|
|
- }
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ width: 2px;
|
|
|
+ height: 100%;
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ background: #4285f4;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ .tooltip {
|
|
|
+ padding-left: 8px;
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|