import _ from "lodash"; import { getuuid, isEqual } from "@/utils/index.js"; import { EventBus } from "@/utils/eventBus"; import moment from "moment"; 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(); EventBus.$on('onEditSignCallback', this.handleEditSignCallback); EventBus.$on('onFormEditSignCancel', this.handleEditSignCancel); }, unmounted() { this.formFields = {};//清空当前填写的数据 EventBus.$off('onEditSignCallback', this.handleEditSignCallback); EventBus.$off('onFormEditSignCancel', this.handleEditSignCancel); }, methods: { getRecords() { const records = []; const { nickName, name } = this.$store.getters; const { oldFormFields, formFields, allFieldsConfig, prefixKey, fieldItemLabel } = this; Object.keys(oldFormFields).forEach(key => { const item = allFieldsConfig[key]; const { label } = item; const oldValue = oldFormFields[key];; const newValue = formFields[key]; let fieldLabelCn = this.$i18n.t(label, "zh_CN"), fieldLabelEn = this.$i18n.t(label, "en_US"); if (!isEqual(oldValue, newValue)) { const record = { userNameCn: nickName, userNameEn: name, key: prefixKey + "_" + key, fieldCn: `${this.$i18n.t(fieldItemLabel, "zh_CN")}` + (fieldLabelCn ? ("-" + fieldLabelCn) : ""), fieldEn: `${this.$i18n.t(fieldItemLabel, "en_US")}` + (fieldLabelEn ? ("-" + fieldLabelEn) : ""), oldValue: oldValue, value: newValue, title: oldValue ? "修改" : "提交", time: moment().format("YYYY-MM-DD HH:mm:ss"), } this.updateZdxgjl(record); records.push(record); } }) return records; }, handleEditSignCancel(data) { if (data.uuid === this.uuid) { this.resetRecord(); this.$emit("resetRecord"); } }, handleEditSignCallback(data) { if (data.uuid === this.uuid) { this.updateRecord(); } }, 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); } }) this.showEditSignDialog(); }, //更新表单数据 updateFormData(key, value) { // 深拷贝当前表单数据,避免直接修改原数据 const cloneFormFields = JSON.parse(JSON.stringify(this.formFields)); this.oldFormFields[key] = cloneFormFields[key]; this.showEditSignDialog(); this.formFields[key] = value; // 清除该表单项的错误状态 if (this.errors[key]) { this.$set(this.errors, key, false); } }, updateRecord() { const records = this.getRecords(); const params = { type: "fieldChanged", newRecord: records, resourceList: this.getZdxgjl(), } //只要有更新就触发更新记录 if(this.templateFillType === "actFill" && this.clickableKey){ this.$emit("onSureModifyRecord", this.clickableKey) this.clickableKey = ""; } setTimeout(() => { EventBus.$emit('onModifyRecord', params,) }, 0); }, //更新记录 showEditSignDialog: _.debounce(function () { //如果oldFormFields中存在空值,说明是第一次填写,直接更新记录 const flag = Object.values(this.oldFormFields).every((val)=>{ // 0 算有值 if (val === 0) return true; if (val === "0") return true; // 其他情况:非 null、非 undefined、非空字符串 return val != null && val != undefined && val != ""; }); const diff = this.compareOldAndCurrentFormFields(); if (!diff && this.templateFillType === "actFill" && flag) { setTimeout(() => {//延迟200ms打开弹窗,避免弹窗打开时,会有闪烁 EventBus.$emit('showEditSignDialog', { uuid: this.uuid }); }, 200); }else{ this.updateRecord(); } }, 100), // 比较oldFormFields和formFields的值是否相等,只要有一对不相等就返回false compareOldAndCurrentFormFields() { // 遍历oldFormFields,检查每个键值对 for (const key in this.oldFormFields) { if (this.oldFormFields.hasOwnProperty(key)) { const oldValue = this.oldFormFields[key]; const currentValue = this.formFields[key]; // 检查当前formFields中是否也包含此key,且值是否相等 if (this.formFields.hasOwnProperty(key)) { // 比较值是否相等 if (JSON.stringify(oldValue) !== JSON.stringify(currentValue)) { return false; } } else { // 如果formFields中没有此key,说明不相等 return false; } } } return true; }, 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, } }, getClickableItem(sItem) { return { label: "", type: "clickable", fillType: sItem.subFillType || sItem.fillType, parentLabel: sItem.label, } }, getSubItem(sItem) { return { label: "", options: sItem.subOptions || [], fillType: sItem.subFillType || sItem.fillType, parentLabel: sItem.label, } }, // 根据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 } = currentConfig; //如果是更新的话,优先使用formFields中的值 if (update) { result[otherCode] = formFields[otherCode] || formData[otherCode] || ''; } else { result[otherCode] = formData[otherCode] || formFields[otherCode] || ''; } config[otherCode] = { label: "template.common.other", 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 } } // 检查compareTo字段 if (currentConfig.compareTo && formData[currentConfig.compareTo] && result[key]) { const compareToValue = formData[currentConfig.compareTo]; const currentValue = result[key]; this.compareFieldsIsEqual(currentValue, compareToValue, key) } }); // 处理可能存在的直接otherCode字段 if (item.config?.otherCode) { config[item.config?.otherCode] = item.config?.otherCode; } } }); // 处理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]); if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段 formFields[o.otherCode] = ""; } } else if (o.subType === "select") { const isSelectedOther = this.isShowOther(formFields[o.subKey]); if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段 formFields[o.otherCode] = ""; } } } if (this.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 }; }, // 判断值是否为空 isValueEmpty(value) { if (value === null || value === undefined || value === '') { return true; } if (typeof value === 'string' && value.trim() === '') { return true; } if (Array.isArray(value) && value.length === 0) { return true; } return false; }, getFormData() { // 同时执行数据校验和子组件校验 const validateResult = this.validateFormData(); const subComponentValidateResult = this.validateSubComponents(); // const subComponentValidateResult = {valid: true, error: ''}; console.log(subComponentValidateResult,validateResult,"subComponentValidateResult") 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); 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" && (currentFieldConfig.compareTo || compKey)) { const compareToKey = compKey || currentFieldConfig.compareTo; const compareToValue = this.formFields[compareToKey]; this.compareFieldsIsEqual(val, compareToValue, key); } }, 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 }); // 清除该表单项的错误状态 if (this.errors[key]) { this.$set(this.errors, key, false); } }, //复制 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 = {}; }, } }