You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
351 lines
10 KiB
351 lines
10 KiB
<!-- @format -->
|
|
|
|
<template>
|
|
<a-col
|
|
:span="span"
|
|
class="ns-form-item"
|
|
:class="getFormItemClass"
|
|
v-if="getIfShow"
|
|
v-show="getShow">
|
|
<a-form-item v-if="getFormItemDisplay" v-bind="formItemProps">
|
|
<template #[item]="data" v-for="item in Object.keys(getSlots)">
|
|
<slot :name="schema.field + '_' + item" v-bind="data || {}"></slot>
|
|
</template>
|
|
<component :is="schema.component" v-bind="formProps">
|
|
<template #[item]="data" v-for="item in Object.keys($slots)">
|
|
<slot :name="item" v-bind="data || {}" :field="schema.field"></slot>
|
|
</template>
|
|
</component>
|
|
<!-- <div class="ns-tips">-->
|
|
<!-- <slot :name="`${schema.field}_tips`"></slot>-->
|
|
<!-- </div>-->
|
|
</a-form-item>
|
|
<template v-else>
|
|
<component :is="schema.component" v-bind="formProps">
|
|
<template #[item]="data" v-for="item in Object.keys($slots)">
|
|
<slot :name="item" v-bind="data || {}"></slot>
|
|
</template>
|
|
</component>
|
|
<!-- <div class="ns-tips">-->
|
|
<!-- <slot :name="`${schema.field}_tips`"></slot>-->
|
|
<!-- </div>-->
|
|
</template>
|
|
</a-col>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import type { PropType } from 'vue';
|
|
import { computed, defineComponent, inject, nextTick, provide, ref, unref } from 'vue';
|
|
import {
|
|
forEach,
|
|
isArray,
|
|
isBoolean,
|
|
isFunction,
|
|
isObject,
|
|
isString,
|
|
isUndefined,
|
|
mapKeys,
|
|
upperFirst,
|
|
get,
|
|
cloneDeep,
|
|
} from 'lodash-es';
|
|
import { isInputType } from '/nerv-lib/component/form/form-util';
|
|
import { useParams } from '/nerv-lib/use/use-params';
|
|
|
|
enum prefix {
|
|
'请选择',
|
|
'请输入',
|
|
}
|
|
|
|
export default defineComponent({
|
|
name: 'NsFormItem',
|
|
components: {},
|
|
props: {
|
|
span: Number,
|
|
schema: {
|
|
type: Object as PropType<FormSchema>,
|
|
default: () => ({}),
|
|
},
|
|
show: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
formModel: {
|
|
type: Object as PropType<Recordable>,
|
|
default: () => ({}),
|
|
},
|
|
index: {
|
|
type: Number,
|
|
default: 0,
|
|
},
|
|
},
|
|
setup(props, { slots }) {
|
|
const components = inject('components', () => ({}))();
|
|
const setFormModel = inject('setFormModel') as Function;
|
|
const getFormModel = inject('getFormModel') as Function;
|
|
const submit = inject('submit') as Function;
|
|
const validateRef = ref({});
|
|
const formLayout = inject('formLayout');
|
|
|
|
const { getParams } = useParams();
|
|
|
|
const getSlots = computed(() => {
|
|
const { schema } = props;
|
|
return mapKeys(slots, (_val, key) => {
|
|
return schema.field ? key.replace(schema.field + '_', '') : key;
|
|
});
|
|
});
|
|
|
|
provide(
|
|
'rules',
|
|
computed(() => {
|
|
return props.schema?.rules || [];
|
|
}),
|
|
);
|
|
|
|
const formItemProps = computed(() => {
|
|
const {
|
|
schema: { field, rules, label, component, autoLink, formItemProps, extra, style },
|
|
} = props;
|
|
const tableComponent = ['nsTable'];
|
|
let nsClass = '';
|
|
component && tableComponent.includes(component) && (nsClass = 'ns-form-item-validate-self');
|
|
return {
|
|
class: nsClass,
|
|
name: field,
|
|
rules: rules || [],
|
|
label: label,
|
|
autoLink: autoLink || true,
|
|
extra: extra,
|
|
style,
|
|
...formItemProps,
|
|
...validateRef.value,
|
|
};
|
|
});
|
|
|
|
const getFormItemDisplay = computed(() => {
|
|
const { schema } = props;
|
|
return schema.displayFormItem !== false;
|
|
});
|
|
|
|
const getFormItemClass = computed(() => {
|
|
const { schema } = props;
|
|
return schema.class;
|
|
});
|
|
|
|
const getDisabled = computed(() => {
|
|
const { dynamicDisabled } = props.schema;
|
|
if (dynamicDisabled) {
|
|
if (isBoolean(dynamicDisabled)) {
|
|
return { disabled: dynamicDisabled };
|
|
}
|
|
if (isFunction(dynamicDisabled)) {
|
|
return { disabled: dynamicDisabled(props.formModel) };
|
|
}
|
|
return {};
|
|
}
|
|
return {};
|
|
});
|
|
|
|
const getIfShow = computed(() => {
|
|
const { ifShow } = props.schema;
|
|
let isIfShow = true;
|
|
if (isBoolean(ifShow)) {
|
|
isIfShow = ifShow;
|
|
}
|
|
if (isFunction(ifShow)) {
|
|
isIfShow = ifShow(props.formModel);
|
|
}
|
|
// 不显示时候删除属性
|
|
if (!isIfShow) {
|
|
setFormModel(props.schema.field, null);
|
|
}
|
|
|
|
return isIfShow && props.show;
|
|
});
|
|
|
|
const getShow = computed(() => {
|
|
const { show } = props.schema;
|
|
let isShow = true;
|
|
if (isBoolean(show)) {
|
|
isShow = show;
|
|
}
|
|
if (isFunction(show)) {
|
|
isShow = show(props.formModel);
|
|
}
|
|
return isShow;
|
|
});
|
|
// console.log(props.schema?.field, getShow.value, props.schema);
|
|
|
|
const getDynamicParams = computed(() => {
|
|
const { dynamicParams, defaultParams, componentProps = {} } = props.schema;
|
|
const { params = {} } = componentProps;
|
|
if (dynamicParams) {
|
|
const data = getParams(props.formModel, dynamicParams, { ...params, ...defaultParams });
|
|
// console.log('getParams', data);
|
|
return data;
|
|
} else {
|
|
return { ...params, ...defaultParams };
|
|
}
|
|
});
|
|
|
|
/**
|
|
* 检测requiredParams是否全部获得数据
|
|
* @param params
|
|
*/
|
|
function checkRequiredParams(params: Recordable) {
|
|
const { dynamicParams } = props.schema;
|
|
let { requiredParams } = props.schema;
|
|
if (requiredParams) {
|
|
if (requiredParams === true) requiredParams = dynamicParams as any;
|
|
if (isFunction(requiredParams)) {
|
|
console.error(
|
|
'Property dynamicParams of props cannot set to Function when using requiredParams',
|
|
);
|
|
return false;
|
|
} else {
|
|
if (isString(requiredParams)) {
|
|
if (isUndefined(params[requiredParams])) return false;
|
|
} else if (isArray(requiredParams)) {
|
|
for (let i = 0, l = requiredParams.length; i < l; i++) {
|
|
if (isUndefined(params[requiredParams[i]])) return false;
|
|
}
|
|
} else if (isObject(requiredParams)) {
|
|
const keys = Object.keys(requiredParams);
|
|
for (let i = 0, l = keys.length; i < l; i++) {
|
|
if (isUndefined(params[keys[i]])) return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
const formProps = computed(() => {
|
|
const { formModel } = props;
|
|
const {
|
|
component,
|
|
field,
|
|
label,
|
|
dynamicParams,
|
|
changeEvent = 'change',
|
|
valueField,
|
|
addModel = [],
|
|
autoAddLink = false,
|
|
autoSubmit = false,
|
|
componentProps,
|
|
} = props.schema;
|
|
const isCheck =
|
|
component && ['NsSwitch', 'NsCheckbox', 'Switch', 'Checkbox'].includes(component);
|
|
const eventKey = `on${upperFirst(changeEvent)}`;
|
|
const attr: Recordable = {};
|
|
const isInput = isInputType(component);
|
|
if (isInput) {
|
|
attr.allowClear = true;
|
|
}
|
|
|
|
// const { placeholder } = componentProps;
|
|
// // 赋予初始提示符
|
|
// componentProps['placeholder'] = placeholder || `${prefix[Number(isInput)]}${label}`;
|
|
|
|
const propsData: Recordable = {
|
|
field,
|
|
dynamicParams,
|
|
...attr,
|
|
size: 'default',
|
|
...unref(getComponentsProps),
|
|
...unref(getDisabled),
|
|
};
|
|
|
|
// 如果有值
|
|
if (getDynamicParams.value) {
|
|
if (props.schema?.requiredParams) {
|
|
if (checkRequiredParams(getDynamicParams.value)) {
|
|
propsData.params = getDynamicParams.value;
|
|
propsData.checkRequiredParams = true;
|
|
} else {
|
|
propsData.checkRequiredParams = false;
|
|
}
|
|
} else {
|
|
propsData.params = getDynamicParams.value;
|
|
}
|
|
}
|
|
|
|
const bindValue: Recordable = {
|
|
[valueField || (isCheck ? 'checked' : 'value')]: props.formModel[field],
|
|
};
|
|
const on = {
|
|
[eventKey]: (...args: Nullable<Recordable>[]) => {
|
|
const [e] = args;
|
|
if (propsData[eventKey]) {
|
|
(propsData[eventKey] as Function)(...args);
|
|
}
|
|
const target = e ? e.target : null;
|
|
const value = target ? (isCheck ? target.checked : target.value) : e;
|
|
|
|
setFormModel(field, value);
|
|
|
|
if (isArray(addModel)) {
|
|
addModel.forEach((item) => {
|
|
setFormModel(item, args[1] && args[1][item]);
|
|
});
|
|
} else {
|
|
forEach(addModel as any, (value, key) => {
|
|
setFormModel(key, args[1] && get(args[1], value));
|
|
});
|
|
}
|
|
|
|
if (autoAddLink) {
|
|
const fieldLink = getFormModel('fieldLink') || {};
|
|
fieldLink[field] = args[1];
|
|
setFormModel('fieldLink', fieldLink);
|
|
}
|
|
|
|
autoSubmit && nextTick(submit as any);
|
|
},
|
|
onValidateChange: (text: Object | undefined) => {
|
|
if (isUndefined(text)) text = {};
|
|
validateRef.value = text;
|
|
},
|
|
};
|
|
|
|
return {
|
|
...propsData,
|
|
...on,
|
|
...bindValue,
|
|
formModel,
|
|
};
|
|
});
|
|
|
|
const getComponentsProps = computed(() => {
|
|
const { componentProps = {} } = unref(props).schema;
|
|
return componentProps;
|
|
});
|
|
|
|
return {
|
|
formItemProps,
|
|
formProps,
|
|
getShow,
|
|
getIfShow,
|
|
components,
|
|
getFormItemDisplay,
|
|
getFormItemClass,
|
|
getSlots,
|
|
formLayout,
|
|
cloneDeep,
|
|
};
|
|
},
|
|
beforeCreate() {
|
|
this.$options.components = this.components;
|
|
},
|
|
});
|
|
</script>
|
|
<style lang="less" scoped>
|
|
.ns-tips {
|
|
height: auto;
|
|
line-height: 32px;
|
|
width: auto;
|
|
display: inline-block;
|
|
}
|
|
</style>
|
|
|