import _ from "lodash"; import { getuuid, isEqual, isValueEmpty } from "@/utils/index.js"; import { isShowOtherByCheckboxTree } from "@/utils/formPackageCommon.js"; export default { inject: ["getZdxgjl", "updateZdxgjl"], watch: { formData: { immediate: true, deep: true, // 深度监听,以便检测嵌套对象变化 handler(v) { if (v) { this.handleFormField(true); } } }, fieldItemLabel: { immediate: true, deep: true, // 深度监听,以便检测嵌套对象变化 handler(v) { if (v) { console.log(v, "fieldItemLabel") } } }, formConfig: { immediate: true, deep: true, // 深度监听,以便检测嵌套对象变化 handler(v) { this.handleFormField(); } } }, data() { return { uuid: getuuid(), oldFormFields: {}, clickableKey: "", } }, mounted() { this.handleFormField(); }, unmounted() { this.formFields = {};//清空当前填写的数据 }, methods: { onSelectChange(key, val, type) { // 获取对应的配置 const currentConfig = this.allFieldsConfig[key]; if (currentConfig?.selectTo) { this.formFields[currentConfig?.selectTo] = val; } this.onValueChangeCompareTo(key, val); this.formFields[key] = val; this.$emit("select", { key, value: val, type, ...this.formFields }); // 清除该表单项的错误状态 if (this.errors[key]) { this.$set(this.errors, key, false); } }, //试剂/仪器等弹窗提交 onRegentSubmit(data, inputValue, key, item) { this.updateFormData(key, inputValue); this.$emit("onRegentSubmit", { selectInfo: data, inputValue, key, config: item }); }, getRegentItem(item, fieldCode = "type") { const type = item[fieldCode]; const fillType = fieldCode === "type" ? item.fillType : (item.subFillType || item.fillType); return { label: "", type, fillType, parentLabel: item.label, filledCodes: item.filledCodes, qxbdType: item.qxbdType, checkType: item.checkType, regentFillType: item.regentFillType, } }, handleClickButton(key) { this.$emit("clickButton", key) }, getFillType(type) { const typeObj = { actFill: "orange-border",//实际填写的边框颜色 green: "green-border", preFill: "blue-border",//预填写的边框颜色 } return typeObj[type] || "" }, onInputNumberChange(key, val) { this.formFields[key] = val; // 清除该表单项的错误状态 if (this.errors[key]) { this.$set(this.errors, key, false); } }, //批量更新表单数据 batchUpdateFormData(data) { const cloneFormFields = JSON.parse(JSON.stringify(this.formFields)); Object.keys(data).forEach(key => { this.oldFormFields[key] = cloneFormFields[key]; this.formFields[key] = data[key]; // 清除该表单项的错误状态 if (this.errors[key]) { this.$set(this.errors, key, false); } }) }, //更新表单数据 updateFormData(key, value, data) { const { isUpdateRecord, signData } = data || {}; // 深拷贝当前表单数据,避免直接修改原数据 const cloneFormFields = JSON.parse(JSON.stringify(this.formFields)); this.oldFormFields[key] = cloneFormFields[key]; this.formFields[key] = value; // 清除该表单项的错误状态 if (this.errors[key]) { this.$set(this.errors, key, false); } if (isUpdateRecord) { setTimeout(() => { this.$refs[key][0].handleUpdateRecord(signData, { oldValue: this.oldFormFields[key], inputValue: value }); }, 10); } }, handleClickable(sItem, key) { if (this.templateFillType !== 'actFill') { return } this.clickableKey = key; this.$emit("clickable", sItem) }, //根据span判断一行显示几列 getSpanClass(sItem) { const spanArr = ["full-row", "", "three-row"] if (sItem.span) { return spanArr[sItem.span - 1] } return "" }, //获取其他下拉框的配置 getOtherItem(sItem) { return { label: sItem.otherLabel ? this.$t(sItem.otherLabel) : this.$t("template.common.other"), fillType: sItem.fillType, maxlength: sItem.otherMaxlength || 50, parentLabel: sItem.label, options: sItem.otherOptions || [], } }, getRadioOtherItem(sItem) { return { // label: sItem.otherLabel ? this.$t(sItem.otherLabel) : this.$t("template.common.other"), fillType: sItem.fillType, maxlength: sItem.otherMaxlength || 50, parentLabel: sItem.label, } }, getClickableItem(sItem) { return { label: "", type: "clickable", fillType: sItem.subFillType || sItem.fillType, parentLabel: sItem.label, } }, getSubItem(sItem) { const config = { label: "", options: sItem.subOptions || [], fillType: sItem.subFillType || sItem.fillType, parentLabel: sItem.label, } if (sItem.subDisabled) { config.disabled = sItem.subDisabled; } return config; }, //获取第三个的配置 getThirdItem(sItem) { const config = { label: "", options: sItem.thirdOptions || [], fillType: sItem.thirdFillType, parentLabel: sItem.label, maxlength: sItem.thirdMaxlength || 50, } if (sItem.thirdDisabled) { config.disabled = sItem.thirdDisabled; } return config; }, // 根据formConfig回填form表单数据 handleFormField(update = false) { const result = {}; let config = {}; const { formConfig, formData, formFields } = this; // 遍历配置 formConfig.forEach((item) => { if (item.config) { // 合并配置项 config = { ...config, ...item.config } // 处理每个配置项 Object.keys(item.config).forEach(key => { const currentConfig = item.config[key]; let value = formData[key]; // 如果formFields中已经有值,保持原值(用户输入或之前设置的值) if (formFields[key] !== null && formFields[key] !== undefined && formFields[key] !== '' // typeof formFields[key] !== 'object' ) { // 保留原值,不使用formData中的值 result[key] = formFields[key]; } else { // 使用formData中的值 result[key] = value; } // 处理特殊字段 - "其他"字段 if (currentConfig.otherCode) { const { otherCode, type } = currentConfig; //如果是更新的话,优先使用formFields中的值 if (update) { result[otherCode] = formFields[otherCode] || formData[otherCode] || ''; } else { result[otherCode] = formData[otherCode] || formFields[otherCode] || ''; } config[otherCode] = { label: "template.common.other", parentType: type, parentKey: key, type: "input", fillType: currentConfig.fillType } } if (currentConfig.thirdOtherCode) { const { thirdOtherCode, type } = currentConfig; //如果是更新的话,优先使用formFields中的值 if (update) { result[thirdOtherCode] = formFields[thirdOtherCode] || formData[thirdOtherCode] || ''; } else { result[thirdOtherCode] = formData[thirdOtherCode] || formFields[thirdOtherCode] || ''; } config[thirdOtherCode] = { label: "template.common.other", parentType: type, parentKey: key, type: "input", fillType: currentConfig.fillType } } if (currentConfig.subKey) { const { subKey } = currentConfig; if (update) { result[subKey] = formFields[subKey] || formData[subKey] || ''; } else { result[subKey] = formData[subKey] || formFields[subKey] || ''; } config[subKey] = { label: currentConfig.label, subKey, type: currentConfig.subType, fillType: currentConfig.subFillType || currentConfig.fillType, selectTo: currentConfig.selectTo } } if (currentConfig.thirdKey) { const { thirdKey } = currentConfig; if (update) { result[thirdKey] = formFields[thirdKey] || formData[thirdKey] || ''; } else { result[thirdKey] = formFields[thirdKey] || formData[thirdKey] || ''; } config[thirdKey] = { label: currentConfig.label, thirdKey, type: currentConfig.thirdType, fillType: currentConfig.thirdFillType, selectTo: currentConfig.selectTo } } if (currentConfig.fourthKey) { const { fourthKey } = currentConfig; if (update) { result[fourthKey] = formFields[fourthKey] || formData[fourthKey] || ''; } else { result[fourthKey] = formFields[fourthKey] || formData[fourthKey] || ''; } config[fourthKey] = { label: currentConfig.label, fourthKey, type: currentConfig.fourthType, fillType: currentConfig.fourthFillType, selectTo: currentConfig.selectTo } } // 检查compareTo字段 if (currentConfig.compareTo && formData[currentConfig.compareTo] && result[key]) { const compareToValue = formData[currentConfig.compareTo]; const currentValue = result[key]; this.compareFieldsIsEqual(currentValue, compareToValue, key) } // 检查compareTo字段 if (currentConfig.subCompareTo && formData[currentConfig.subCompareTo] && result[currentConfig.subKey]) { const compareToValue = formData[currentConfig.subCompareTo]; const currentValue = result[currentConfig.subKey]; this.compareFieldsIsEqual(currentValue, compareToValue, currentConfig.subKey) } if (currentConfig.otherCodeCompareTo && formData[currentConfig.otherCodeCompareTo] && result[currentConfig.otherCode]) { const compareToValue = formData[currentConfig.otherCodeCompareTo]; const currentValue = result[currentConfig.otherCode]; this.compareFieldsIsEqual(currentValue, compareToValue, currentConfig.otherCode) } }); // 处理可能存在的直接otherCode字段 if (item.config?.otherCode) { config[item.config?.otherCode] = item.config?.otherCode; } if (item.config?.thirdOtherCode) { config[item.config?.thirdOtherCode] = item.config?.thirdOtherCode; } } }); // 处理selectInfo_开头的字段,步骤表单需要保留selectInfo_开头的字段 const selectInfoKeys = Object.keys(formData).filter(key => key.startsWith("selectInfo_")); selectInfoKeys.forEach(key => { result[key] = formData[key]; }) // 更新表单字段 this.formFields = result; this.allFieldsConfig = config; }, //比较值是否相等 compareFieldsIsEqual(currentValue, compareToValue, key) { if (!currentValue || !compareToValue) return; // 如果当前值与compareTo字段的值不相等,则设置橙色背景 if (isEqual(currentValue, compareToValue)) { // 如果相等,移除橙色背景(如果之前设置了的话) this.$set(this.orangeBgFields, key, false); } else { this.$set(this.orangeBgFields, key, true); } }, //判断是否禁用 getDisabled() { const { item } = this; const { fillType } = item; if (item.hasOwnProperty("disabled")) { return item.disabled } else { if (fillType === "actFill") {//当模板状态是实际填写时,只有当fillType是actFill时才能填写 return this.templateFillType !== "actFill" } else if (fillType === "preFill") {//当模板状态是预填写时,只有当fillType是preFill才能填写 return this.templateFillType !== "preFill" } else { return true } } }, // 表单数据校验 validateFormData() { const { formFields, allFieldsConfig } = this; const errors = []; // 清空之前的错误状态 this.errors = {}; for (const key in allFieldsConfig) { const o = allFieldsConfig[key]; if (o.otherCode) {// if (o.type === "select") { const isSelectedOther = this.isShowOther(formFields[key], o); if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段 formFields[o.otherCode] = ""; } } else if (o.subType === "select") { const isSelectedOther = this.isShowOther(formFields[o.subKey], o); if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段 formFields[o.otherCode] = ""; } } else if (o.type === "radioAndOther") { const isSelectedOther = this.isShowOtherByRadioAndOther(formFields[key], o); if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段 formFields[o.otherCode] = ""; } } } if (o.type === "attachment" && o.fillType === this.templateFillType) { const attValue = formFields[key]; if (!attValue || attValue == "[]") { errors.push({ field: key, label: o.label, error: "请上传附件" }); this.$set(this.errors, key, true); } } else if (o.type === "fqyq" && o.fillType === this.templateFillType) { const fqyqValue = formFields[key] || {}; const { mainRadio, subRadio, inputValue } = fqyqValue; if (!mainRadio) { errors.push({ field: key, label: o.label, error: "请选择是否在规定时间完成" }); this.$set(this.errors, key, true); } else { if (mainRadio === "是") { if (!subRadio) { errors.push({ field: key, label: o.label, error: "请选择是否在规定时间完成" }); this.$set(this.errors, key, true); } else if (!inputValue) { errors.push({ field: key, label: o.label, error: "请输入信息" }); this.$set(this.errors, key, true); } } } continue } else if (o.type === "checkboxTree" && o.fillType === this.templateFillType) { const checkboxTreeValue = formFields[key] || {}; const { checkedValues = [], otherValues = {} } = checkboxTreeValue;; const { options = [] } = o; //需要校验第一层是否有选中项 const parentOptions = options.map(item => item.label); const isChecked = checkedValues.some(option => { return option.checked === true; }); //获取所有选中的选项 const allCheckedOptions = checkedValues.filter(item => item.checked).map(item => item.label); //再筛选出需要显示其他输入框的选项 const otherOptions = allCheckedOptions.filter((label) => isShowOtherByCheckboxTree(label)) const isHasOtherInfo = otherOptions.every(item => otherValues[item]); console.log(isChecked, isHasOtherInfo, "isChecked") if (!isChecked || !isHasOtherInfo) { errors.push({ field: key, label: o.label, error: "请选择方法学验证" }); this.$set(this.errors, key, true); } continue } else if (o.type === "radioAndOther" && o.fillType === this.templateFillType) { const radioValue = formFields[key] || {}; const { otherCode } = o; const otherValue = formFields[otherCode] || ""; const isShow = this.isShowOtherByRadioAndOther(radioValue, o) if (isShow && !otherValue) { errors.push({ field: key, label: o.label, error: "请输入信息" }); this.$set(this.errors, key, true); } // if (!radioValue) { // errors.push({ // field: key, // label: o.label, // error: "请选择方法学验证" // }); // this.$set(this.errors, key, true); // } continue } if (isValueEmpty(formFields[key])) { // 其他字段需要判断是否显示再校验 if (o.label === "template.common.other" && !this.isShowOther(formFields[o.parentKey])) { continue } //span的字段不校验 if (o.type === "span" || o.type === "text" || o.type === "button") { continue } if (o.fillType === this.templateFillType && !o.disabled) { let prefix = ""; if (o.type === "input" || o.type === "inputNumber" || o.type === "textarea") { prefix = "填写"; } else { prefix = "选择"; } const errorItem = { field: key, label: o.label, error: `请${prefix}${o.label}` }; errors.push(errorItem); this.$set(this.errors, key, true); } } } console.log(errors, "errors") return { valid: errors.length === 0, errors: errors }; }, getFormData() { // 同时执行数据校验和子组件校验 const validateResult = this.validateFormData(); const subComponentValidateResult = this.validateSubComponents(); // const subComponentValidateResult = {valid: true, error: ''}; return new Promise((resolve, reject) => { if (validateResult.valid && subComponentValidateResult.valid) { resolve(this.formFields); } else if (!validateResult.valid) { // this.$message.error("表单内容未填完,请填写后再提交"); reject(validateResult.errors[0].error); } else { reject(subComponentValidateResult.error); } }); }, // 子组件校验钩子方法,子组件可以重写此方法来添加额外的校验逻辑 validateSubComponents() { return { valid: true, error: '' }; }, //直接获取表单数据,不做校验 getFilledFormData() { return this.formFields; }, getFormDataByKey(key) { return this.formFields[key]; }, onBlur(key, val) { // compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色 this.onValueChangeCompareTo(key, val); if (this.errors[key]) { this.$set(this.errors, key, false); } this.$emit("blur", { key, value: val, ...this.formFields }); }, onValueChangeCompareTo(key, val, compKey) { // compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色 const currentFieldConfig = this.allFieldsConfig[key]; if (currentFieldConfig && currentFieldConfig.fillType === "actFill") { if ((currentFieldConfig.compareTo || compKey)) { const compareToKey = compKey || currentFieldConfig.compareTo; const compareToValue = this.formFields[compareToKey]; this.compareFieldsIsEqual(val, compareToValue, key); } if (currentFieldConfig.otherCodeCompareTo && this.formFields[currentFieldConfig.otherCodeCompareTo] && this.formFields[currentFieldConfig.otherCode]) { const compareToValue = this.formFields[currentFieldConfig.otherCodeCompareTo]; const currentValue = this.formFields[currentFieldConfig.otherCode]; this.compareFieldsIsEqual(currentValue, compareToValue, currentFieldConfig.otherCode) } if(currentFieldConfig.subCompareTo && this.formFields[currentFieldConfig.subCompareTo] && this.formFields[currentFieldConfig.subKey]){ const compareToValue = this.formFields[currentFieldConfig.subCompareTo]; const currentValue = this.formFields[currentFieldConfig.subKey]; this.compareFieldsIsEqual(currentValue, compareToValue, currentFieldConfig.subKey) } } }, onAttachmentChange(key, val) { this.formFields[key] = val; // 清除该表单项的错误状态 if (this.errors[key]) { this.$set(this.errors, key, false); } // 如果是checkboxList类型,需要处理otherValues if (val && typeof val === 'object' && val.otherValues) { // 将otherValues中的每个值也保存到formFields中 Object.keys(val.otherValues).forEach(otherCode => { this.formFields[otherCode] = val.otherValues[otherCode]; }); } }, //复制 onCopy(config, key) { const { formFields } = this; if (config.copyFrom) { formFields[key] = formFields[config.copyFrom]; this.onBlur(key, formFields[key]); } }, resetRecord(key) { this.formFields = { ...this.formFields, ...this.oldFormFields }; this.oldFormFields = {}; }, } }