华西海圻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.

587 lines
26 KiB

  1. import _ from "lodash";
  2. import { getuuid, isEqual, isValueEmpty } from "@/utils/index.js";
  3. import { isShowOtherByCheckboxTree } from "@/utils/formPackageCommon.js";
  4. export default {
  5. inject: ["getZdxgjl", "updateZdxgjl"],
  6. watch: {
  7. formData: {
  8. immediate: true,
  9. deep: true, // 深度监听,以便检测嵌套对象变化
  10. handler(v) {
  11. if (v) {
  12. this.handleFormField(true);
  13. }
  14. }
  15. },
  16. fieldItemLabel: {
  17. immediate: true,
  18. deep: true, // 深度监听,以便检测嵌套对象变化
  19. handler(v) {
  20. if (v) {
  21. console.log(v, "fieldItemLabel")
  22. }
  23. }
  24. },
  25. formConfig: {
  26. immediate: true,
  27. deep: true, // 深度监听,以便检测嵌套对象变化
  28. handler(v) {
  29. this.handleFormField();
  30. }
  31. }
  32. },
  33. data() {
  34. return {
  35. uuid: getuuid(),
  36. oldFormFields: {},
  37. clickableKey: "",
  38. }
  39. },
  40. mounted() {
  41. this.handleFormField();
  42. },
  43. unmounted() {
  44. this.formFields = {};//清空当前填写的数据
  45. },
  46. methods: {
  47. onSelectChange(key, val, type) {
  48. // 获取对应的配置
  49. const currentConfig = this.allFieldsConfig[key];
  50. if (currentConfig?.selectTo) {
  51. this.formFields[currentConfig?.selectTo] = val;
  52. }
  53. this.onValueChangeCompareTo(key, val);
  54. this.formFields[key] = val;
  55. this.$emit("select", { key, value: val, type, ...this.formFields });
  56. // 清除该表单项的错误状态
  57. if (this.errors[key]) {
  58. this.$set(this.errors, key, false);
  59. }
  60. },
  61. //试剂/仪器等弹窗提交
  62. onRegentSubmit(data, inputValue, key, item) {
  63. this.updateFormData(key, inputValue);
  64. this.$emit("onRegentSubmit", { selectInfo: data, inputValue, key, config: item });
  65. },
  66. getRegentItem(item, fieldCode = "type") {
  67. const type = item[fieldCode];
  68. const fillType = fieldCode === "type" ? item.fillType : (item.subFillType || item.fillType);
  69. return {
  70. label: "",
  71. type,
  72. fillType,
  73. parentLabel: item.label,
  74. filledCodes: item.filledCodes,
  75. qxbdType: item.qxbdType,
  76. checkType: item.checkType,
  77. regentFillType: item.regentFillType,
  78. }
  79. },
  80. handleClickButton(key) {
  81. this.$emit("clickButton", key)
  82. },
  83. getFillType(type) {
  84. const typeObj = {
  85. actFill: "orange-border",//实际填写的边框颜色
  86. green: "green-border",
  87. preFill: "blue-border",//预填写的边框颜色
  88. }
  89. return typeObj[type] || ""
  90. },
  91. onInputNumberChange(key, val) {
  92. this.formFields[key] = val;
  93. // 清除该表单项的错误状态
  94. if (this.errors[key]) {
  95. this.$set(this.errors, key, false);
  96. }
  97. },
  98. //批量更新表单数据
  99. batchUpdateFormData(data) {
  100. const cloneFormFields = JSON.parse(JSON.stringify(this.formFields));
  101. Object.keys(data).forEach(key => {
  102. this.oldFormFields[key] = cloneFormFields[key];
  103. this.formFields[key] = data[key];
  104. // 清除该表单项的错误状态
  105. if (this.errors[key]) {
  106. this.$set(this.errors, key, false);
  107. }
  108. })
  109. },
  110. //更新表单数据
  111. updateFormData(key, value, data) {
  112. const { isUpdateRecord, signData } = data || {};
  113. // 深拷贝当前表单数据,避免直接修改原数据
  114. const cloneFormFields = JSON.parse(JSON.stringify(this.formFields));
  115. this.oldFormFields[key] = cloneFormFields[key];
  116. this.formFields[key] = value;
  117. // 清除该表单项的错误状态
  118. if (this.errors[key]) {
  119. this.$set(this.errors, key, false);
  120. }
  121. if (isUpdateRecord) {
  122. setTimeout(() => {
  123. this.$refs[key][0].handleUpdateRecord(signData, { oldValue: this.oldFormFields[key], inputValue: value });
  124. }, 10);
  125. }
  126. },
  127. handleClickable(sItem, key) {
  128. if (this.templateFillType !== 'actFill') {
  129. return
  130. }
  131. this.clickableKey = key;
  132. this.$emit("clickable", sItem)
  133. },
  134. //根据span判断一行显示几列
  135. getSpanClass(sItem) {
  136. const spanArr = ["full-row", "", "three-row"]
  137. if (sItem.span) {
  138. return spanArr[sItem.span - 1]
  139. }
  140. return ""
  141. },
  142. //获取其他下拉框的配置
  143. getOtherItem(sItem) {
  144. return {
  145. label: sItem.otherLabel ? this.$t(sItem.otherLabel) : this.$t("template.common.other"),
  146. fillType: sItem.fillType,
  147. maxlength: sItem.otherMaxlength || 50,
  148. parentLabel: sItem.label,
  149. options: sItem.otherOptions || [],
  150. }
  151. },
  152. getRadioOtherItem(sItem) {
  153. return {
  154. // label: sItem.otherLabel ? this.$t(sItem.otherLabel) : this.$t("template.common.other"),
  155. fillType: sItem.fillType,
  156. maxlength: sItem.otherMaxlength || 50,
  157. parentLabel: sItem.label,
  158. }
  159. },
  160. getClickableItem(sItem) {
  161. return {
  162. label: "",
  163. type: "clickable",
  164. fillType: sItem.subFillType || sItem.fillType,
  165. parentLabel: sItem.label,
  166. }
  167. },
  168. getSubItem(sItem) {
  169. const config = {
  170. label: "",
  171. options: sItem.subOptions || [],
  172. fillType: sItem.subFillType || sItem.fillType,
  173. parentLabel: sItem.label,
  174. }
  175. if (sItem.subDisabled) {
  176. config.disabled = sItem.subDisabled;
  177. }
  178. return config;
  179. },
  180. //获取第三个的配置
  181. getThirdItem(sItem) {
  182. const config = {
  183. label: "",
  184. options: sItem.thirdOptions || [],
  185. fillType: sItem.thirdFillType,
  186. parentLabel: sItem.label,
  187. maxlength: sItem.thirdMaxlength || 50,
  188. }
  189. if (sItem.thirdDisabled) {
  190. config.disabled = sItem.thirdDisabled;
  191. }
  192. return config;
  193. },
  194. // 根据formConfig回填form表单数据
  195. handleFormField(update = false) {
  196. const result = {};
  197. let config = {};
  198. const { formConfig, formData, formFields } = this;
  199. // 遍历配置
  200. formConfig.forEach((item) => {
  201. if (item.config) {
  202. // 合并配置项
  203. config = { ...config, ...item.config }
  204. // 处理每个配置项
  205. Object.keys(item.config).forEach(key => {
  206. const currentConfig = item.config[key];
  207. let value = formData[key];
  208. // 如果formFields中已经有值,保持原值(用户输入或之前设置的值)
  209. if (formFields[key] !== null &&
  210. formFields[key] !== undefined &&
  211. formFields[key] !== ''
  212. // typeof formFields[key] !== 'object'
  213. ) {
  214. // 保留原值,不使用formData中的值
  215. result[key] = formFields[key];
  216. } else {
  217. // 使用formData中的值
  218. result[key] = value;
  219. }
  220. // 处理特殊字段 - "其他"字段
  221. if (currentConfig.otherCode) {
  222. const { otherCode, type } = currentConfig;
  223. //如果是更新的话,优先使用formFields中的值
  224. if (update) {
  225. result[otherCode] = formFields[otherCode] || formData[otherCode] || '';
  226. } else {
  227. result[otherCode] = formData[otherCode] || formFields[otherCode] || '';
  228. }
  229. config[otherCode] = { label: "template.common.other", parentType: type, parentKey: key, type: "input", fillType: currentConfig.fillType }
  230. }
  231. if (currentConfig.thirdOtherCode) {
  232. const { thirdOtherCode, type } = currentConfig;
  233. //如果是更新的话,优先使用formFields中的值
  234. if (update) {
  235. result[thirdOtherCode] = formFields[thirdOtherCode] || formData[thirdOtherCode] || '';
  236. } else {
  237. result[thirdOtherCode] = formData[thirdOtherCode] || formFields[thirdOtherCode] || '';
  238. }
  239. config[thirdOtherCode] = { label: "template.common.other", parentType: type, parentKey: key, type: "input", fillType: currentConfig.fillType }
  240. }
  241. if (currentConfig.subKey) {
  242. const { subKey } = currentConfig;
  243. if (update) {
  244. result[subKey] = formFields[subKey] || formData[subKey] || '';
  245. } else {
  246. result[subKey] = formData[subKey] || formFields[subKey] || '';
  247. }
  248. config[subKey] = { label: currentConfig.label, subKey, type: currentConfig.subType, fillType: currentConfig.subFillType || currentConfig.fillType, selectTo: currentConfig.selectTo }
  249. }
  250. if (currentConfig.thirdKey) {
  251. const { thirdKey } = currentConfig;
  252. if (update) {
  253. result[thirdKey] = formFields[thirdKey] || formData[thirdKey] || '';
  254. } else {
  255. result[thirdKey] = formFields[thirdKey] || formData[thirdKey] || '';
  256. }
  257. config[thirdKey] = { label: currentConfig.label, thirdKey, type: currentConfig.thirdType, fillType: currentConfig.thirdFillType, selectTo: currentConfig.selectTo }
  258. }
  259. if (currentConfig.fourthKey) {
  260. const { fourthKey } = currentConfig;
  261. if (update) {
  262. result[fourthKey] = formFields[fourthKey] || formData[fourthKey] || '';
  263. } else {
  264. result[fourthKey] = formFields[fourthKey] || formData[fourthKey] || '';
  265. }
  266. config[fourthKey] = { label: currentConfig.label, fourthKey, type: currentConfig.fourthType, fillType: currentConfig.fourthFillType, selectTo: currentConfig.selectTo }
  267. }
  268. // 检查compareTo字段
  269. if (currentConfig.compareTo && formData[currentConfig.compareTo] && result[key]) {
  270. const compareToValue = formData[currentConfig.compareTo];
  271. const currentValue = result[key];
  272. this.compareFieldsIsEqual(currentValue, compareToValue, key)
  273. }
  274. // 检查compareTo字段
  275. if (currentConfig.subCompareTo && formData[currentConfig.subCompareTo] && result[currentConfig.subKey]) {
  276. const compareToValue = formData[currentConfig.subCompareTo];
  277. const currentValue = result[currentConfig.subKey];
  278. this.compareFieldsIsEqual(currentValue, compareToValue, currentConfig.subKey)
  279. }
  280. if (currentConfig.otherCodeCompareTo && formData[currentConfig.otherCodeCompareTo] && result[currentConfig.otherCode]) {
  281. const compareToValue = formData[currentConfig.otherCodeCompareTo];
  282. const currentValue = result[currentConfig.otherCode];
  283. this.compareFieldsIsEqual(currentValue, compareToValue, currentConfig.otherCode)
  284. }
  285. });
  286. // 处理可能存在的直接otherCode字段
  287. if (item.config?.otherCode) {
  288. config[item.config?.otherCode] = item.config?.otherCode;
  289. }
  290. if (item.config?.thirdOtherCode) {
  291. config[item.config?.thirdOtherCode] = item.config?.thirdOtherCode;
  292. }
  293. }
  294. });
  295. // 处理selectInfo_开头的字段,步骤表单需要保留selectInfo_开头的字段
  296. const selectInfoKeys = Object.keys(formData).filter(key => key.startsWith("selectInfo_"));
  297. selectInfoKeys.forEach(key => {
  298. result[key] = formData[key];
  299. })
  300. // 更新表单字段
  301. this.formFields = result;
  302. this.allFieldsConfig = config;
  303. },
  304. //比较值是否相等
  305. compareFieldsIsEqual(currentValue, compareToValue, key) {
  306. if (!currentValue || !compareToValue) return;
  307. // 如果当前值与compareTo字段的值不相等,则设置橙色背景
  308. if (isEqual(currentValue, compareToValue)) {
  309. // 如果相等,移除橙色背景(如果之前设置了的话)
  310. this.$set(this.orangeBgFields, key, false);
  311. } else {
  312. this.$set(this.orangeBgFields, key, true);
  313. }
  314. },
  315. //判断是否禁用
  316. getDisabled() {
  317. const { item } = this;
  318. const { fillType } = item;
  319. if (item.hasOwnProperty("disabled")) {
  320. return item.disabled
  321. } else {
  322. if (fillType === "actFill") {//当模板状态是实际填写时,只有当fillType是actFill时才能填写
  323. return this.templateFillType !== "actFill"
  324. } else if (fillType === "preFill") {//当模板状态是预填写时,只有当fillType是preFill才能填写
  325. return this.templateFillType !== "preFill"
  326. } else {
  327. return true
  328. }
  329. }
  330. },
  331. // 表单数据校验
  332. validateFormData() {
  333. const { formFields, allFieldsConfig } = this;
  334. const errors = [];
  335. // 清空之前的错误状态
  336. this.errors = {};
  337. for (const key in allFieldsConfig) {
  338. const o = allFieldsConfig[key];
  339. if (o.otherCode) {//
  340. if (o.type === "select") {
  341. const isSelectedOther = this.isShowOther(formFields[key], o);
  342. if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
  343. formFields[o.otherCode] = "";
  344. }
  345. } else if (o.subType === "select") {
  346. const isSelectedOther = this.isShowOther(formFields[o.subKey], o);
  347. if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
  348. formFields[o.otherCode] = "";
  349. }
  350. } else if (o.type === "radioAndOther") {
  351. const isSelectedOther = this.isShowOtherByRadioAndOther(formFields[key], o);
  352. if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
  353. formFields[o.otherCode] = "";
  354. }
  355. }
  356. }
  357. if (o.type === "attachment" && o.fillType === this.templateFillType) {
  358. const attValue = formFields[key];
  359. if (!attValue || attValue == "[]") {
  360. errors.push({
  361. field: key,
  362. label: o.label,
  363. error: "请上传附件"
  364. });
  365. this.$set(this.errors, key, true);
  366. }
  367. } else if (o.type === "fqyq" && o.fillType === this.templateFillType) {
  368. const fqyqValue = formFields[key] || {};
  369. const { mainRadio, subRadio, inputValue } = fqyqValue;
  370. if (!mainRadio) {
  371. errors.push({
  372. field: key,
  373. label: o.label,
  374. error: "请选择是否在规定时间完成"
  375. });
  376. this.$set(this.errors, key, true);
  377. } else {
  378. if (mainRadio === "是") {
  379. if (!subRadio) {
  380. errors.push({
  381. field: key,
  382. label: o.label,
  383. error: "请选择是否在规定时间完成"
  384. });
  385. this.$set(this.errors, key, true);
  386. } else if (!inputValue) {
  387. errors.push({
  388. field: key,
  389. label: o.label,
  390. error: "请输入信息"
  391. });
  392. this.$set(this.errors, key, true);
  393. }
  394. }
  395. }
  396. continue
  397. } else if (o.type === "checkboxTree" && o.fillType === this.templateFillType) {
  398. const checkboxTreeValue = formFields[key] || {};
  399. const { checkedValues = [], otherValues = {} } = checkboxTreeValue;;
  400. const { options = [] } = o;
  401. //需要校验第一层是否有选中项
  402. const parentOptions = options.map(item => item.label);
  403. const isChecked = checkedValues.some(option => {
  404. return option.checked === true;
  405. });
  406. //获取所有选中的选项
  407. const allCheckedOptions = checkedValues.filter(item => item.checked).map(item => item.label);
  408. //再筛选出需要显示其他输入框的选项
  409. const otherOptions = allCheckedOptions.filter((label) => isShowOtherByCheckboxTree(label))
  410. const isHasOtherInfo = otherOptions.every(item => otherValues[item]);
  411. console.log(isChecked, isHasOtherInfo, "isChecked")
  412. if (!isChecked || !isHasOtherInfo) {
  413. errors.push({
  414. field: key,
  415. label: o.label,
  416. error: "请选择方法学验证"
  417. });
  418. this.$set(this.errors, key, true);
  419. }
  420. continue
  421. } else if (o.type === "radioAndOther" && o.fillType === this.templateFillType) {
  422. const radioValue = formFields[key] || {};
  423. const { otherCode } = o;
  424. const otherValue = formFields[otherCode] || "";
  425. const isShow = this.isShowOtherByRadioAndOther(radioValue, o)
  426. if (isShow && !otherValue) {
  427. errors.push({
  428. field: key,
  429. label: o.label,
  430. error: "请输入信息"
  431. });
  432. this.$set(this.errors, key, true);
  433. }
  434. // if (!radioValue) {
  435. // errors.push({
  436. // field: key,
  437. // label: o.label,
  438. // error: "请选择方法学验证"
  439. // });
  440. // this.$set(this.errors, key, true);
  441. // }
  442. continue
  443. }
  444. if (isValueEmpty(formFields[key])) {
  445. // 其他字段需要判断是否显示再校验
  446. if (o.label === "template.common.other" && !this.isShowOther(formFields[o.parentKey])) {
  447. continue
  448. }
  449. //span的字段不校验
  450. if (o.type === "span" || o.type === "text" || o.type === "button") {
  451. continue
  452. }
  453. if (o.fillType === this.templateFillType && !o.disabled) {
  454. let prefix = "";
  455. if (o.type === "input" || o.type === "inputNumber" || o.type === "textarea") {
  456. prefix = "填写";
  457. } else {
  458. prefix = "选择";
  459. }
  460. const errorItem = {
  461. field: key,
  462. label: o.label,
  463. error: `${prefix}${o.label}`
  464. };
  465. errors.push(errorItem);
  466. this.$set(this.errors, key, true);
  467. }
  468. }
  469. }
  470. console.log(errors, "errors")
  471. return {
  472. valid: errors.length === 0,
  473. errors: errors
  474. };
  475. },
  476. getFormData() {
  477. // 同时执行数据校验和子组件校验
  478. const validateResult = this.validateFormData();
  479. const subComponentValidateResult = this.validateSubComponents();
  480. // const subComponentValidateResult = {valid: true, error: ''};
  481. return new Promise((resolve, reject) => {
  482. if (validateResult.valid && subComponentValidateResult.valid) {
  483. resolve(this.formFields);
  484. } else if (!validateResult.valid) {
  485. // this.$message.error("表单内容未填完,请填写后再提交");
  486. reject(validateResult.errors[0].error);
  487. } else {
  488. reject(subComponentValidateResult.error);
  489. }
  490. });
  491. },
  492. // 子组件校验钩子方法,子组件可以重写此方法来添加额外的校验逻辑
  493. validateSubComponents() {
  494. return {
  495. valid: true,
  496. error: ''
  497. };
  498. },
  499. //直接获取表单数据,不做校验
  500. getFilledFormData() {
  501. return this.formFields;
  502. },
  503. getFormDataByKey(key) {
  504. return this.formFields[key];
  505. },
  506. onBlur(key, val) {
  507. // compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色
  508. this.onValueChangeCompareTo(key, val);
  509. if (this.errors[key]) {
  510. this.$set(this.errors, key, false);
  511. }
  512. this.$emit("blur", { key, value: val, ...this.formFields });
  513. },
  514. onValueChangeCompareTo(key, val, compKey) {
  515. // compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色
  516. const currentFieldConfig = this.allFieldsConfig[key];
  517. if (currentFieldConfig && currentFieldConfig.fillType === "actFill") {
  518. if ((currentFieldConfig.compareTo || compKey)) {
  519. const compareToKey = compKey || currentFieldConfig.compareTo;
  520. const compareToValue = this.formFields[compareToKey];
  521. this.compareFieldsIsEqual(val, compareToValue, key);
  522. }
  523. if (currentFieldConfig.otherCodeCompareTo && this.formFields[currentFieldConfig.otherCodeCompareTo] && this.formFields[currentFieldConfig.otherCode]) {
  524. const compareToValue = this.formFields[currentFieldConfig.otherCodeCompareTo];
  525. const currentValue = this.formFields[currentFieldConfig.otherCode];
  526. this.compareFieldsIsEqual(currentValue, compareToValue, currentFieldConfig.otherCode)
  527. }
  528. if(currentFieldConfig.subCompareTo && this.formFields[currentFieldConfig.subCompareTo] && this.formFields[currentFieldConfig.subKey]){
  529. const compareToValue = this.formFields[currentFieldConfig.subCompareTo];
  530. const currentValue = this.formFields[currentFieldConfig.subKey];
  531. this.compareFieldsIsEqual(currentValue, compareToValue, currentFieldConfig.subKey)
  532. }
  533. }
  534. },
  535. onAttachmentChange(key, val) {
  536. this.formFields[key] = val;
  537. // 清除该表单项的错误状态
  538. if (this.errors[key]) {
  539. this.$set(this.errors, key, false);
  540. }
  541. // 如果是checkboxList类型,需要处理otherValues
  542. if (val && typeof val === 'object' && val.otherValues) {
  543. // 将otherValues中的每个值也保存到formFields中
  544. Object.keys(val.otherValues).forEach(otherCode => {
  545. this.formFields[otherCode] = val.otherValues[otherCode];
  546. });
  547. }
  548. },
  549. //复制
  550. onCopy(config, key) {
  551. const { formFields } = this;
  552. if (config.copyFrom) {
  553. formFields[key] = formFields[config.copyFrom];
  554. this.onBlur(key, formFields[key]);
  555. }
  556. },
  557. resetRecord(key) {
  558. this.formFields = { ...this.formFields, ...this.oldFormFields };
  559. this.oldFormFields = {};
  560. },
  561. }
  562. }