华西海圻ELN前端工程
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.

484 lines
20 KiB

  1. import _ from "lodash";
  2. import { getuuid, isEqual } from "@/utils/index.js";
  3. import { EventBus } from "@/utils/eventBus";
  4. import moment from "moment";
  5. export default {
  6. inject: ["getZdxgjl", "updateZdxgjl"],
  7. watch: {
  8. formData: {
  9. immediate: true,
  10. deep: true, // 深度监听,以便检测嵌套对象变化
  11. handler(v) {
  12. if (v) {
  13. this.handleFormField(true);
  14. }
  15. }
  16. },
  17. fieldItemLabel: {
  18. immediate: true,
  19. deep: true, // 深度监听,以便检测嵌套对象变化
  20. handler(v) {
  21. if (v) {
  22. console.log(v, "fieldItemLabel")
  23. }
  24. }
  25. },
  26. formConfig: {
  27. immediate: true,
  28. deep: true, // 深度监听,以便检测嵌套对象变化
  29. handler(v) {
  30. this.handleFormField();
  31. }
  32. }
  33. },
  34. data() {
  35. return {
  36. uuid: getuuid(),
  37. oldFormFields: {},
  38. clickableKey: "",
  39. }
  40. },
  41. mounted() {
  42. this.handleFormField();
  43. EventBus.$on('onEditSignCallback', this.handleEditSignCallback);
  44. EventBus.$on('onFormEditSignCancel', this.handleEditSignCancel);
  45. },
  46. unmounted() {
  47. this.formFields = {};//清空当前填写的数据
  48. EventBus.$off('onEditSignCallback', this.handleEditSignCallback);
  49. EventBus.$off('onFormEditSignCancel', this.handleEditSignCancel);
  50. },
  51. methods: {
  52. getRecords() {
  53. const records = [];
  54. const { nickName, name } = this.$store.getters;
  55. const { oldFormFields, formFields, allFieldsConfig, prefixKey, fieldItemLabel } = this;
  56. Object.keys(oldFormFields).forEach(key => {
  57. const item = allFieldsConfig[key];
  58. const { label } = item;
  59. const oldValue = oldFormFields[key];;
  60. const newValue = formFields[key];
  61. let fieldLabelCn = this.$i18n.t(label, "zh_CN"), fieldLabelEn = this.$i18n.t(label, "en_US");
  62. if (!isEqual(oldValue, newValue)) {
  63. const record = {
  64. userNameCn: nickName,
  65. userNameEn: name,
  66. key: prefixKey + "_" + key,
  67. fieldCn: `${this.$i18n.t(fieldItemLabel, "zh_CN")}` + (fieldLabelCn ? ("-" + fieldLabelCn) : ""),
  68. fieldEn: `${this.$i18n.t(fieldItemLabel, "en_US")}` + (fieldLabelEn ? ("-" + fieldLabelEn) : ""),
  69. oldValue: oldValue,
  70. value: newValue,
  71. title: oldValue ? "修改" : "提交",
  72. time: moment().format("YYYY-MM-DD HH:mm:ss"),
  73. }
  74. this.updateZdxgjl(record);
  75. records.push(record);
  76. }
  77. })
  78. return records;
  79. },
  80. handleEditSignCancel(data) {
  81. if (data.uuid === this.uuid) {
  82. this.resetRecord();
  83. this.$emit("resetRecord");
  84. }
  85. },
  86. handleEditSignCallback(data) {
  87. if (data.uuid === this.uuid) {
  88. this.updateRecord();
  89. }
  90. },
  91. handleClickButton(key) {
  92. this.$emit("clickButton", key)
  93. },
  94. getFillType(type) {
  95. const typeObj = {
  96. actFill: "orange-border",//实际填写的边框颜色
  97. green: "green-border",
  98. preFill: "blue-border",//预填写的边框颜色
  99. }
  100. return typeObj[type] || ""
  101. },
  102. onInputNumberChange(key, val) {
  103. this.formFields[key] = val;
  104. // 清除该表单项的错误状态
  105. if (this.errors[key]) {
  106. this.$set(this.errors, key, false);
  107. }
  108. },
  109. //批量更新表单数据
  110. batchUpdateFormData(data) {
  111. const cloneFormFields = JSON.parse(JSON.stringify(this.formFields));
  112. Object.keys(data).forEach(key => {
  113. this.oldFormFields[key] = cloneFormFields[key];
  114. this.formFields[key] = data[key];
  115. // 清除该表单项的错误状态
  116. if (this.errors[key]) {
  117. this.$set(this.errors, key, false);
  118. }
  119. })
  120. this.showEditSignDialog();
  121. },
  122. //更新表单数据
  123. updateFormData(key, value) {
  124. // 深拷贝当前表单数据,避免直接修改原数据
  125. const cloneFormFields = JSON.parse(JSON.stringify(this.formFields));
  126. this.oldFormFields[key] = cloneFormFields[key];
  127. this.showEditSignDialog();
  128. this.formFields[key] = value;
  129. // 清除该表单项的错误状态
  130. if (this.errors[key]) {
  131. this.$set(this.errors, key, false);
  132. }
  133. },
  134. updateRecord() {
  135. const records = this.getRecords();
  136. const params = {
  137. type: "fieldChanged",
  138. newRecord: records,
  139. resourceList: this.getZdxgjl(),
  140. }
  141. //只要有更新就触发更新记录
  142. if(this.templateFillType === "actFill" && this.clickableKey){
  143. this.$emit("onSureModifyRecord", this.clickableKey)
  144. this.clickableKey = "";
  145. }
  146. setTimeout(() => {
  147. EventBus.$emit('onModifyRecord', params,)
  148. }, 0);
  149. },
  150. //更新记录
  151. showEditSignDialog: _.debounce(function () {
  152. //如果oldFormFields中存在空值,说明是第一次填写,直接更新记录
  153. const flag = Object.values(this.oldFormFields).every((val)=>{
  154. // 0 算有值
  155. if (val === 0) return true;
  156. if (val === "0") return true;
  157. // 其他情况:非 null、非 undefined、非空字符串
  158. return val != null && val != undefined && val != "";
  159. });
  160. const diff = this.compareOldAndCurrentFormFields();
  161. if (!diff && this.templateFillType === "actFill" && flag) {
  162. setTimeout(() => {//延迟200ms打开弹窗,避免弹窗打开时,会有闪烁
  163. EventBus.$emit('showEditSignDialog', { uuid: this.uuid });
  164. }, 200);
  165. }else{
  166. this.updateRecord();
  167. }
  168. }, 100),
  169. // 比较oldFormFields和formFields的值是否相等,只要有一对不相等就返回false
  170. compareOldAndCurrentFormFields() {
  171. // 遍历oldFormFields,检查每个键值对
  172. for (const key in this.oldFormFields) {
  173. if (this.oldFormFields.hasOwnProperty(key)) {
  174. const oldValue = this.oldFormFields[key];
  175. const currentValue = this.formFields[key];
  176. // 检查当前formFields中是否也包含此key,且值是否相等
  177. if (this.formFields.hasOwnProperty(key)) {
  178. // 比较值是否相等
  179. if (JSON.stringify(oldValue) !== JSON.stringify(currentValue)) {
  180. return false;
  181. }
  182. } else {
  183. // 如果formFields中没有此key,说明不相等
  184. return false;
  185. }
  186. }
  187. }
  188. return true;
  189. },
  190. handleClickable(sItem, key) {
  191. if (this.templateFillType !== 'actFill') {
  192. return
  193. }
  194. this.clickableKey = key;
  195. this.$emit("clickable", sItem)
  196. },
  197. //根据span判断一行显示几列
  198. getSpanClass(sItem) {
  199. const spanArr = ["full-row", "", "three-row"]
  200. if (sItem.span) {
  201. return spanArr[sItem.span - 1]
  202. }
  203. return ""
  204. },
  205. //获取其他下拉框的配置
  206. getOtherItem(sItem) {
  207. return {
  208. label: sItem.otherLabel ? this.$t(sItem.otherLabel) : this.$t("template.common.other"),
  209. fillType: sItem.fillType,
  210. maxlength: sItem.otherMaxlength || 50,
  211. parentLabel: sItem.label,
  212. }
  213. },
  214. getClickableItem(sItem) {
  215. return {
  216. label: "",
  217. type: "clickable",
  218. fillType: sItem.subFillType || sItem.fillType,
  219. parentLabel: sItem.label,
  220. }
  221. },
  222. getSubItem(sItem) {
  223. return {
  224. label: "",
  225. options: sItem.subOptions || [],
  226. fillType: sItem.subFillType || sItem.fillType,
  227. parentLabel: sItem.label,
  228. }
  229. },
  230. // 根据formConfig回填form表单数据
  231. handleFormField(update = false) {
  232. const result = {};
  233. let config = {};
  234. const { formConfig, formData, formFields } = this;
  235. // 遍历配置
  236. formConfig.forEach((item) => {
  237. if (item.config) {
  238. // 合并配置项
  239. config = { ...config, ...item.config }
  240. // 处理每个配置项
  241. Object.keys(item.config).forEach(key => {
  242. const currentConfig = item.config[key];
  243. let value = formData[key];
  244. // 如果formFields中已经有值,保持原值(用户输入或之前设置的值)
  245. if (formFields[key] !== null &&
  246. formFields[key] !== undefined &&
  247. formFields[key] !== ''
  248. // typeof formFields[key] !== 'object'
  249. ) {
  250. // 保留原值,不使用formData中的值
  251. result[key] = formFields[key];
  252. } else {
  253. // 使用formData中的值
  254. result[key] = value;
  255. }
  256. // 处理特殊字段 - "其他"字段
  257. if (currentConfig.otherCode) {
  258. const { otherCode } = currentConfig;
  259. //如果是更新的话,优先使用formFields中的值
  260. if (update) {
  261. result[otherCode] = formFields[otherCode] || formData[otherCode] || '';
  262. } else {
  263. result[otherCode] = formData[otherCode] || formFields[otherCode] || '';
  264. }
  265. config[otherCode] = { label: "template.common.other", parentKey: key, type: "input", fillType: currentConfig.fillType }
  266. }
  267. if (currentConfig.subKey) {
  268. const { subKey } = currentConfig;
  269. if (update) {
  270. result[subKey] = formFields[subKey] || formData[subKey] || '';
  271. } else {
  272. result[subKey] = formData[subKey] || formFields[subKey] || '';
  273. }
  274. config[subKey] = { label: currentConfig.label, subKey, type: currentConfig.subType, fillType: currentConfig.subFillType || currentConfig.fillType, selectTo: currentConfig.selectTo }
  275. }
  276. // 检查compareTo字段
  277. if (currentConfig.compareTo && formData[currentConfig.compareTo] && result[key]) {
  278. const compareToValue = formData[currentConfig.compareTo];
  279. const currentValue = result[key];
  280. this.compareFieldsIsEqual(currentValue, compareToValue, key)
  281. }
  282. });
  283. // 处理可能存在的直接otherCode字段
  284. if (item.config?.otherCode) {
  285. config[item.config?.otherCode] = item.config?.otherCode;
  286. }
  287. }
  288. });
  289. // 处理selectInfo_开头的字段,步骤表单需要保留selectInfo_开头的字段
  290. const selectInfoKeys = Object.keys(formData).filter(key => key.startsWith("selectInfo_"));
  291. selectInfoKeys.forEach(key => {
  292. result[key] = formData[key];
  293. })
  294. // 更新表单字段
  295. this.formFields = result;
  296. this.allFieldsConfig = config;
  297. },
  298. //比较值是否相等
  299. compareFieldsIsEqual(currentValue, compareToValue, key) {
  300. if (!currentValue || !compareToValue) return;
  301. // 如果当前值与compareTo字段的值不相等,则设置橙色背景
  302. if (isEqual(currentValue, compareToValue)) {
  303. // 如果相等,移除橙色背景(如果之前设置了的话)
  304. this.$set(this.orangeBgFields, key, false);
  305. } else {
  306. this.$set(this.orangeBgFields, key, true);
  307. }
  308. },
  309. //判断是否禁用
  310. getDisabled() {
  311. const { item } = this;
  312. const { fillType } = item;
  313. if (item.hasOwnProperty("disabled")) {
  314. return item.disabled
  315. } else {
  316. if (fillType === "actFill") {//当模板状态是实际填写时,只有当fillType是actFill时才能填写
  317. return this.templateFillType !== "actFill"
  318. } else if (fillType === "preFill") {//当模板状态是预填写时,只有当fillType是preFill才能填写
  319. return this.templateFillType !== "preFill"
  320. } else {
  321. return true
  322. }
  323. }
  324. },
  325. // 表单数据校验
  326. validateFormData() {
  327. const { formFields, allFieldsConfig } = this;
  328. const errors = [];
  329. // 清空之前的错误状态
  330. this.errors = {};
  331. for (const key in allFieldsConfig) {
  332. const o = allFieldsConfig[key];
  333. if (o.otherCode) {//
  334. if (o.type === "select") {
  335. const isSelectedOther = this.isShowOther(formFields[key]);
  336. if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
  337. formFields[o.otherCode] = "";
  338. }
  339. } else if (o.subType === "select") {
  340. const isSelectedOther = this.isShowOther(formFields[o.subKey]);
  341. if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
  342. formFields[o.otherCode] = "";
  343. }
  344. }
  345. }
  346. if (this.isValueEmpty(formFields[key])) {
  347. // 其他字段需要判断是否显示再校验
  348. if (o.label === "template.common.other" && !this.isShowOther(formFields[o.parentKey])) {
  349. continue
  350. }
  351. //span的字段不校验
  352. if (o.type === "span" || o.type === "text" || o.type === "button") {
  353. continue
  354. }
  355. if (o.fillType === this.templateFillType && !o.disabled) {
  356. let prefix = "";
  357. if (o.type === "input" || o.type === "inputNumber" || o.type === "textarea") {
  358. prefix = "填写";
  359. } else {
  360. prefix = "选择";
  361. }
  362. const errorItem = {
  363. field: key,
  364. label: o.label,
  365. error: `${prefix}${o.label}`
  366. };
  367. errors.push(errorItem);
  368. this.$set(this.errors, key, true);
  369. }
  370. }
  371. }
  372. console.log(errors, "errors")
  373. return {
  374. valid: errors.length === 0,
  375. errors: errors
  376. };
  377. },
  378. // 判断值是否为空
  379. isValueEmpty(value) {
  380. if (value === null || value === undefined || value === '') {
  381. return true;
  382. }
  383. if (typeof value === 'string' && value.trim() === '') {
  384. return true;
  385. }
  386. if (Array.isArray(value) && value.length === 0) {
  387. return true;
  388. }
  389. return false;
  390. },
  391. getFormData() {
  392. // 同时执行数据校验和子组件校验
  393. const validateResult = this.validateFormData();
  394. const subComponentValidateResult = this.validateSubComponents();
  395. // const subComponentValidateResult = {valid: true, error: ''};
  396. console.log(subComponentValidateResult,validateResult,"subComponentValidateResult")
  397. return new Promise((resolve, reject) => {
  398. if (validateResult.valid && subComponentValidateResult.valid) {
  399. resolve(this.formFields);
  400. } else if (!validateResult.valid) {
  401. // this.$message.error("表单内容未填完,请填写后再提交");
  402. reject(validateResult.errors[0].error);
  403. } else {
  404. reject(subComponentValidateResult.error);
  405. }
  406. });
  407. },
  408. // 子组件校验钩子方法,子组件可以重写此方法来添加额外的校验逻辑
  409. validateSubComponents() {
  410. return {
  411. valid: true,
  412. error: ''
  413. };
  414. },
  415. //直接获取表单数据,不做校验
  416. getFilledFormData() {
  417. return this.formFields;
  418. },
  419. getFormDataByKey(key) {
  420. return this.formFields[key];
  421. },
  422. onBlur(key, val) {
  423. // compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色
  424. this.onValueChangeCompareTo(key, val);
  425. this.$emit("blur", { key, value: val, ...this.formFields });
  426. },
  427. onValueChangeCompareTo(key, val, compKey) {
  428. // compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色
  429. const currentFieldConfig = this.allFieldsConfig[key];
  430. if (currentFieldConfig && currentFieldConfig.fillType === "actFill" && (currentFieldConfig.compareTo || compKey)) {
  431. const compareToKey = compKey || currentFieldConfig.compareTo;
  432. const compareToValue = this.formFields[compareToKey];
  433. this.compareFieldsIsEqual(val, compareToValue, key);
  434. }
  435. },
  436. onSelectChange(key, val, type) {
  437. // 获取对应的配置
  438. const currentConfig = this.allFieldsConfig[key];
  439. if (currentConfig.selectTo) {
  440. this.formFields[currentConfig.selectTo] = val;
  441. }
  442. this.onValueChangeCompareTo(key, val);
  443. this.formFields[key] = val;
  444. this.$emit("select", { key, value: val, type });
  445. // 清除该表单项的错误状态
  446. if (this.errors[key]) {
  447. this.$set(this.errors, key, false);
  448. }
  449. },
  450. //复制
  451. onCopy(config, key) {
  452. const { formFields } = this;
  453. if (config.copyFrom) {
  454. formFields[key] = formFields[config.copyFrom];
  455. this.onBlur(key, formFields[key]);
  456. }
  457. },
  458. resetRecord(key) {
  459. this.formFields = { ...this.formFields, ...this.oldFormFields };
  460. this.oldFormFields = {};
  461. },
  462. }
  463. }