import { ElFormItem, ElTooltip } from 'element-plus'
import { h, toRef, computed, ref, unref, onErrorCaptured } from 'vue'
import { getInputComponent, getViewComponent, getH5InputComponent } from '../cip-form-input/util'
import { isEmpty, isEmptyObject, isInputEmpty } from '@cip/utils/util'
import { useWatchFieldDepend } from './hooks/use-field-depend'
import { useFieldValue, useSteamUpdateValues } from './hooks/use-model-change'
import { useRules } from './hooks/use-field-rules'
import { isHideLabel, getLabelWidth, UpdateModelQueue } from './util'
import './index.less'
import { useFormInject, useElFormInject } from '../hooks/use-form'
import { useCipConfig } from '@cip/components/hooks/use-cip-config'
export default {
name: 'CipFormItem',
props: {
config: Object, // 字段配置信息
fieldKey: String, // 字段名
model: { // 字段所属model
type: Object,
default: () => ({})
},
readonly: Boolean, // 是否只读-即查看模式
customSlots: Function,
showTemplate: { // 是否展示模版值[注:表单设计中使用]
type: Boolean,
default: false
},
tableDependOnValues: Object,
inTable: {
type: Boolean,
default: false
},
componentKey: String,
grid: [Number, Boolean],
tableData: Array,
onSearch: Function // 供CipSearchForm使用
},
emits: ['update:model'],
setup (props, context) {
onErrorCaptured((e) => {
// el-form-item 在onBeforeUnmount会访问el.value.firstElementChild 由于切换较快的原因会抱错
process.env.NODE_ENV === 'development' && console.log(e)
return false
})
// elForm组件实例
const cipConfig = useCipConfig()
const elForm = useElFormInject()
const cipForm = useFormInject()
const equipment = computed(() => {
return unref(cipForm.equipment) || 'pc'
})
// 一般处于cip-table直接使用的情况下
const notInForm = computed(() => {
return isEmptyObject(elForm)
})
const updateModel = (value) => {
// console.log('updateModel', value)
// if (!notInForm.value) {
// // 因为延迟执行的问题,可能导致数据无法及时有效验证手动调用
// elForm.validateField([formItemConfig.value.ruleKey || props.fieldKey])
// }
context.emit('update:model', value)
}
const updateModelQueue = new UpdateModelQueue(() => props.model, updateModel)
// FormItem及Input组件渲染模式 ['hidden','read','read-write']
const status = computed(() => {
// 为设置则默认开始可读可写模式
const config = formItemConfig.value
if (props.readonly) {
if (config.readable === false) return 'hidden'
return 'read'
}
if (isEmpty(config.readable) && isEmpty(config.writable)) {
return 'read-write'
}
if (config.writable) {
return 'read-write'
} else if (config.readable) {
return 'read'
} else {
return 'hidden'
}
})
// Input组件实际使用的配置
const formItemConfig = computed(() => {
return runningConfig.value || props.config // handleFormConfig()
})
const model = toRef(props, 'model')
const fieldKey = toRef(props, 'fieldKey')
// 仅正对modelValue生效
const changeEffect = computed(() => {
return formItemConfig.value.changeEffect
})
// 3种数据更新方式并行
// modelValue
const [modelValue, updateModelValue] = useFieldValue(fieldKey, model, updateModelQueue, changeEffect)
const otherKey = computed(() => formItemConfig.value?.otherKey)
// otherValue
const [otherValue, updateOtherValue] = useFieldValue(otherKey, model, updateModelQueue)
const { values, streamUpdateModel, clearValues } = useSteamUpdateValues(fieldKey, otherKey, model, updateModel, changeEffect)
// 监听依赖 触发响应事件
const { changeCount, dependOnValues, outDependOnValues, runningConfig } = useWatchFieldDepend(props, context, { updateModelValue, updateOtherValue, clearValues })
const readonly = toRef(props, 'readonly')
// rules
const { usingRules, rules } = useRules(formItemConfig, readonly, status, otherValue, dependOnValues, outDependOnValues)
// Input组件是否展示标记(需要控制form-item内置的margin-bottom)
const childStatus = ref(true)
// FormItem label
const formItemLabel = () => {
// 隐藏label或者label为空时直接返回空字符串
if (formItemConfig.value.hideLabel === true || isEmpty(formItemConfig.value.label)) return ''
// 表单为只读模式下展示样式控制
const labelId = formItemConfig.value.directory ? props.fieldKey : undefined
const result = [h('span', { class: { 'is-readonly': props.readonly }, id: labelId }, [formItemConfig.value.label])]
// 存在说明
if (formItemConfig.value.description) {
const descriptionComp = (