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 = {};
|
|
},
|
|
}
|
|
}
|