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

522 lines
22 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. console.log(item, "type")
  69. return {
  70. label: "",
  71. type,
  72. fillType: item.subFillType || item.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. }
  150. },
  151. getRadioOtherItem(sItem) {
  152. return {
  153. // label: sItem.otherLabel ? this.$t(sItem.otherLabel) : this.$t("template.common.other"),
  154. fillType: sItem.fillType,
  155. maxlength: sItem.otherMaxlength || 50,
  156. parentLabel: sItem.label,
  157. }
  158. },
  159. getClickableItem(sItem) {
  160. return {
  161. label: "",
  162. type: "clickable",
  163. fillType: sItem.subFillType || sItem.fillType,
  164. parentLabel: sItem.label,
  165. }
  166. },
  167. getSubItem(sItem) {
  168. const config = {
  169. label: "",
  170. options: sItem.subOptions || [],
  171. fillType: sItem.subFillType || sItem.fillType,
  172. parentLabel: sItem.label,
  173. }
  174. if (sItem.subDisabled) {
  175. config.disabled = sItem.subDisabled;
  176. }
  177. return config;
  178. },
  179. // 根据formConfig回填form表单数据
  180. handleFormField(update = false) {
  181. const result = {};
  182. let config = {};
  183. const { formConfig, formData, formFields } = this;
  184. // 遍历配置
  185. formConfig.forEach((item) => {
  186. if (item.config) {
  187. // 合并配置项
  188. config = { ...config, ...item.config }
  189. // 处理每个配置项
  190. Object.keys(item.config).forEach(key => {
  191. const currentConfig = item.config[key];
  192. let value = formData[key];
  193. // 如果formFields中已经有值,保持原值(用户输入或之前设置的值)
  194. if (formFields[key] !== null &&
  195. formFields[key] !== undefined &&
  196. formFields[key] !== ''
  197. // typeof formFields[key] !== 'object'
  198. ) {
  199. // 保留原值,不使用formData中的值
  200. result[key] = formFields[key];
  201. } else {
  202. // 使用formData中的值
  203. result[key] = value;
  204. }
  205. // 处理特殊字段 - "其他"字段
  206. if (currentConfig.otherCode) {
  207. const { otherCode, type } = currentConfig;
  208. //如果是更新的话,优先使用formFields中的值
  209. if (update) {
  210. result[otherCode] = formFields[otherCode] || formData[otherCode] || '';
  211. } else {
  212. result[otherCode] = formData[otherCode] || formFields[otherCode] || '';
  213. }
  214. config[otherCode] = { label: "template.common.other", parentType: type, parentKey: key, type: "input", fillType: currentConfig.fillType }
  215. }
  216. if (currentConfig.subKey) {
  217. const { subKey } = currentConfig;
  218. if (update) {
  219. result[subKey] = formFields[subKey] || formData[subKey] || '';
  220. } else {
  221. result[subKey] = formData[subKey] || formFields[subKey] || '';
  222. }
  223. config[subKey] = { label: currentConfig.label, subKey, type: currentConfig.subType, fillType: currentConfig.subFillType || currentConfig.fillType, selectTo: currentConfig.selectTo }
  224. }
  225. // 检查compareTo字段
  226. if (currentConfig.compareTo && formData[currentConfig.compareTo] && result[key]) {
  227. const compareToValue = formData[currentConfig.compareTo];
  228. const currentValue = result[key];
  229. this.compareFieldsIsEqual(currentValue, compareToValue, key)
  230. }
  231. // 检查compareTo字段
  232. if (currentConfig.subCompareTo && formData[currentConfig.subCompareTo] && result[currentConfig.subKey]) {
  233. const compareToValue = formData[currentConfig.subCompareTo];
  234. const currentValue = result[currentConfig.subKey];
  235. this.compareFieldsIsEqual(currentValue, compareToValue, currentConfig.subKey)
  236. }
  237. });
  238. // 处理可能存在的直接otherCode字段
  239. if (item.config?.otherCode) {
  240. config[item.config?.otherCode] = item.config?.otherCode;
  241. }
  242. }
  243. });
  244. // 处理selectInfo_开头的字段,步骤表单需要保留selectInfo_开头的字段
  245. const selectInfoKeys = Object.keys(formData).filter(key => key.startsWith("selectInfo_"));
  246. selectInfoKeys.forEach(key => {
  247. result[key] = formData[key];
  248. })
  249. // 更新表单字段
  250. this.formFields = result;
  251. this.allFieldsConfig = config;
  252. },
  253. //比较值是否相等
  254. compareFieldsIsEqual(currentValue, compareToValue, key) {
  255. if (!currentValue || !compareToValue) return;
  256. // 如果当前值与compareTo字段的值不相等,则设置橙色背景
  257. if (isEqual(currentValue, compareToValue)) {
  258. // 如果相等,移除橙色背景(如果之前设置了的话)
  259. this.$set(this.orangeBgFields, key, false);
  260. } else {
  261. this.$set(this.orangeBgFields, key, true);
  262. }
  263. },
  264. //判断是否禁用
  265. getDisabled() {
  266. const { item } = this;
  267. const { fillType } = item;
  268. if (item.hasOwnProperty("disabled")) {
  269. return item.disabled
  270. } else {
  271. if (fillType === "actFill") {//当模板状态是实际填写时,只有当fillType是actFill时才能填写
  272. return this.templateFillType !== "actFill"
  273. } else if (fillType === "preFill") {//当模板状态是预填写时,只有当fillType是preFill才能填写
  274. return this.templateFillType !== "preFill"
  275. } else {
  276. return true
  277. }
  278. }
  279. },
  280. // 表单数据校验
  281. validateFormData() {
  282. const { formFields, allFieldsConfig } = this;
  283. const errors = [];
  284. // 清空之前的错误状态
  285. this.errors = {};
  286. for (const key in allFieldsConfig) {
  287. const o = allFieldsConfig[key];
  288. if (o.otherCode) {//
  289. if (o.type === "select") {
  290. const isSelectedOther = this.isShowOther(formFields[key],o);
  291. if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
  292. formFields[o.otherCode] = "";
  293. }
  294. } else if (o.subType === "select") {
  295. const isSelectedOther = this.isShowOther(formFields[o.subKey],o);
  296. if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
  297. formFields[o.otherCode] = "";
  298. }
  299. } else if (o.type === "radioAndOther") {
  300. const isSelectedOther = this.isShowOtherByRadioAndOther(formFields[key],o);
  301. if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
  302. formFields[o.otherCode] = "";
  303. }
  304. }
  305. }
  306. if (o.type === "attachment"&&o.fillType === this.templateFillType) {
  307. const attValue = formFields[key];
  308. if (!attValue || attValue == "[]") {
  309. errors.push({
  310. field: key,
  311. label: o.label,
  312. error: "请上传附件"
  313. });
  314. this.$set(this.errors, key, true);
  315. }
  316. } else if (o.type === "fqyq" &&o.fillType === this.templateFillType) {
  317. const fqyqValue = formFields[key] || {};
  318. const {mainRadio, subRadio,inputValue} = fqyqValue;
  319. if (!mainRadio) {
  320. errors.push({
  321. field: key,
  322. label: o.label,
  323. error: "请选择是否在规定时间完成"
  324. });
  325. this.$set(this.errors, key, true);
  326. } else {
  327. if (mainRadio==="是") {
  328. if (!subRadio) {
  329. errors.push({
  330. field: key,
  331. label: o.label,
  332. error: "请选择是否在规定时间完成"
  333. });
  334. this.$set(this.errors, key, true);
  335. }else if(!inputValue){
  336. errors.push({
  337. field: key,
  338. label: o.label,
  339. error: "请输入信息"
  340. });
  341. this.$set(this.errors, key, true);
  342. }
  343. }
  344. }
  345. continue
  346. }else if(o.type === "checkboxTree"&&o.fillType === this.templateFillType){
  347. const checkboxTreeValue = formFields[key] || {};
  348. const {checkedValues=[],otherValues = {}} = checkboxTreeValue;;
  349. const {options = []} = o;
  350. //需要校验第一层是否有选中项
  351. const parentOptions = options.map(item => item.label);
  352. const isChecked = parentOptions.some(option => {
  353. var found = checkedValues.find(item => item.label === option);
  354. return found && found.checked === true;
  355. });
  356. //获取所有选中的选项
  357. const allCheckedOptions = checkedValues.filter(item => item.checked).map(item => item.label);
  358. //再筛选出需要显示其他输入框的选项
  359. const otherOptions = allCheckedOptions.filter((label)=>isShowOtherByCheckboxTree(label))
  360. const isHasOtherInfo = otherOptions.every(item => otherValues[item]);
  361. if (!isChecked || !isHasOtherInfo) {
  362. errors.push({
  363. field: key,
  364. label: o.label,
  365. error: "请选择方法学验证"
  366. });
  367. this.$set(this.errors, key, true);
  368. }
  369. continue
  370. }else if(o.type === "radioAndOther"&&o.fillType === this.templateFillType){
  371. const radioValue = formFields[key] || {};
  372. const {otherCode} = o;
  373. const otherValue = formFields[otherCode] || "";
  374. const isShow = this.isShowOtherByRadioAndOther(radioValue,o)
  375. if(isShow&&!otherValue){
  376. errors.push({
  377. field: key,
  378. label: o.label,
  379. error: "请输入信息"
  380. });
  381. this.$set(this.errors, key, true);
  382. }
  383. // if (!radioValue) {
  384. // errors.push({
  385. // field: key,
  386. // label: o.label,
  387. // error: "请选择方法学验证"
  388. // });
  389. // this.$set(this.errors, key, true);
  390. // }
  391. continue
  392. }
  393. if (isValueEmpty(formFields[key])) {
  394. // 其他字段需要判断是否显示再校验
  395. if (o.label === "template.common.other" && !this.isShowOther(formFields[o.parentKey])) {
  396. continue
  397. }
  398. //span的字段不校验
  399. if (o.type === "span" || o.type === "text" || o.type === "button") {
  400. continue
  401. }
  402. if (o.fillType === this.templateFillType && !o.disabled) {
  403. let prefix = "";
  404. if (o.type === "input" || o.type === "inputNumber" || o.type === "textarea") {
  405. prefix = "填写";
  406. } else {
  407. prefix = "选择";
  408. }
  409. const errorItem = {
  410. field: key,
  411. label: o.label,
  412. error: `${prefix}${o.label}`
  413. };
  414. errors.push(errorItem);
  415. this.$set(this.errors, key, true);
  416. }
  417. }
  418. }
  419. console.log(errors, "errors")
  420. return {
  421. valid: errors.length === 0,
  422. errors: errors
  423. };
  424. },
  425. getFormData() {
  426. // 同时执行数据校验和子组件校验
  427. const validateResult = this.validateFormData();
  428. const subComponentValidateResult = this.validateSubComponents();
  429. // const subComponentValidateResult = {valid: true, error: ''};
  430. return new Promise((resolve, reject) => {
  431. if (validateResult.valid && subComponentValidateResult.valid) {
  432. resolve(this.formFields);
  433. } else if (!validateResult.valid) {
  434. // this.$message.error("表单内容未填完,请填写后再提交");
  435. reject(validateResult.errors[0].error);
  436. } else {
  437. reject(subComponentValidateResult.error);
  438. }
  439. });
  440. },
  441. // 子组件校验钩子方法,子组件可以重写此方法来添加额外的校验逻辑
  442. validateSubComponents() {
  443. return {
  444. valid: true,
  445. error: ''
  446. };
  447. },
  448. //直接获取表单数据,不做校验
  449. getFilledFormData() {
  450. return this.formFields;
  451. },
  452. getFormDataByKey(key) {
  453. return this.formFields[key];
  454. },
  455. onBlur(key, val) {
  456. // compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色
  457. this.onValueChangeCompareTo(key, val);
  458. if (this.errors[key]) {
  459. this.$set(this.errors, key, false);
  460. }
  461. this.$emit("blur", { key, value: val, ...this.formFields });
  462. },
  463. onValueChangeCompareTo(key, val, compKey) {
  464. // compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色
  465. const currentFieldConfig = this.allFieldsConfig[key];
  466. if (currentFieldConfig && currentFieldConfig.fillType === "actFill" && (currentFieldConfig.compareTo || compKey)) {
  467. const compareToKey = compKey || currentFieldConfig.compareTo;
  468. const compareToValue = this.formFields[compareToKey];
  469. this.compareFieldsIsEqual(val, compareToValue, key);
  470. }
  471. },
  472. onAttachmentChange(key, val) {
  473. this.formFields[key] = val;
  474. // 清除该表单项的错误状态
  475. if (this.errors[key]) {
  476. this.$set(this.errors, key, false);
  477. }
  478. // 如果是checkboxList类型,需要处理otherValues
  479. if (val && typeof val === 'object' && val.otherValues) {
  480. // 将otherValues中的每个值也保存到formFields中
  481. Object.keys(val.otherValues).forEach(otherCode => {
  482. this.formFields[otherCode] = val.otherValues[otherCode];
  483. });
  484. }
  485. },
  486. //复制
  487. onCopy(config, key) {
  488. const { formFields } = this;
  489. if (config.copyFrom) {
  490. formFields[key] = formFields[config.copyFrom];
  491. this.onBlur(key, formFields[key]);
  492. }
  493. },
  494. resetRecord(key) {
  495. this.formFields = { ...this.formFields, ...this.oldFormFields };
  496. this.oldFormFields = {};
  497. },
  498. }
  499. }