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

456 lines
19 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. },
  44. unmounted() {
  45. this.formFields = {};//清空当前填写的数据
  46. },
  47. methods: {
  48. onSelectChange(key, val, type) {
  49. // 获取对应的配置
  50. const currentConfig = this.allFieldsConfig[key];
  51. if (currentConfig.selectTo) {
  52. this.formFields[currentConfig.selectTo] = val;
  53. }
  54. this.onValueChangeCompareTo(key, val);
  55. this.formFields[key] = val;
  56. this.$emit("select", { key, value: val, type,...this.formFields });
  57. // 清除该表单项的错误状态
  58. if (this.errors[key]) {
  59. this.$set(this.errors, key, false);
  60. }
  61. },
  62. //试剂/仪器等弹窗提交
  63. onRegentSubmit(data,inputValue,key,item){
  64. this.updateFormData(key,inputValue);
  65. this.$emit("onRegentSubmit", {selectInfo:data,inputValue,key,config:item});
  66. },
  67. getRegentItem(item,fieldCode="type"){
  68. const type = item[fieldCode] ;
  69. console.log(item,"type")
  70. return {
  71. label: "",
  72. type,
  73. fillType: item.subFillType || item.fillType,
  74. parentLabel: item.label,
  75. filledCodes:item.filledCodes,
  76. }
  77. },
  78. handleClickButton(key) {
  79. this.$emit("clickButton", key)
  80. },
  81. getFillType(type) {
  82. const typeObj = {
  83. actFill: "orange-border",//实际填写的边框颜色
  84. green: "green-border",
  85. preFill: "blue-border",//预填写的边框颜色
  86. }
  87. return typeObj[type] || ""
  88. },
  89. onInputNumberChange(key, val) {
  90. this.formFields[key] = val;
  91. // 清除该表单项的错误状态
  92. if (this.errors[key]) {
  93. this.$set(this.errors, key, false);
  94. }
  95. },
  96. //批量更新表单数据
  97. batchUpdateFormData(data) {
  98. const cloneFormFields = JSON.parse(JSON.stringify(this.formFields));
  99. Object.keys(data).forEach(key => {
  100. this.oldFormFields[key] = cloneFormFields[key];
  101. this.formFields[key] = data[key];
  102. // 清除该表单项的错误状态
  103. if (this.errors[key]) {
  104. this.$set(this.errors, key, false);
  105. }
  106. })
  107. },
  108. //更新表单数据
  109. updateFormData(key, value,data) {
  110. const {isUpdateRecord,signData} = data || {};
  111. // 深拷贝当前表单数据,避免直接修改原数据
  112. const cloneFormFields = JSON.parse(JSON.stringify(this.formFields));
  113. this.oldFormFields[key] = cloneFormFields[key];
  114. this.formFields[key] = value;
  115. // 清除该表单项的错误状态
  116. if (this.errors[key]) {
  117. this.$set(this.errors, key, false);
  118. }
  119. if(isUpdateRecord){
  120. setTimeout(() => {
  121. this.$refs[key][0].handleUpdateRecord(signData,{oldValue:this.oldFormFields[key],inputValue:value});
  122. }, 10);
  123. }
  124. },
  125. handleClickable(sItem, key) {
  126. if (this.templateFillType !== 'actFill') {
  127. return
  128. }
  129. this.clickableKey = key;
  130. this.$emit("clickable", sItem)
  131. },
  132. //根据span判断一行显示几列
  133. getSpanClass(sItem) {
  134. const spanArr = ["full-row", "", "three-row"]
  135. if (sItem.span) {
  136. return spanArr[sItem.span - 1]
  137. }
  138. return ""
  139. },
  140. //获取其他下拉框的配置
  141. getOtherItem(sItem) {
  142. return {
  143. label: sItem.otherLabel ? this.$t(sItem.otherLabel) : this.$t("template.common.other"),
  144. fillType: sItem.fillType,
  145. maxlength: sItem.otherMaxlength || 50,
  146. parentLabel: sItem.label,
  147. }
  148. },
  149. getRadioOtherItem(sItem) {
  150. return {
  151. // label: sItem.otherLabel ? this.$t(sItem.otherLabel) : this.$t("template.common.other"),
  152. fillType: sItem.fillType,
  153. maxlength: sItem.otherMaxlength || 50,
  154. parentLabel: sItem.label,
  155. }
  156. },
  157. getClickableItem(sItem) {
  158. return {
  159. label: "",
  160. type: "clickable",
  161. fillType: sItem.subFillType || sItem.fillType,
  162. parentLabel: sItem.label,
  163. }
  164. },
  165. getSubItem(sItem) {
  166. const config = {
  167. label: "",
  168. options: sItem.subOptions || [],
  169. fillType: sItem.subFillType || sItem.fillType,
  170. parentLabel: sItem.label,
  171. }
  172. if(sItem.subDisabled){
  173. config.disabled = sItem.subDisabled;
  174. }
  175. return config;
  176. },
  177. // 根据formConfig回填form表单数据
  178. handleFormField(update = false) {
  179. const result = {};
  180. let config = {};
  181. const { formConfig, formData, formFields } = this;
  182. // 遍历配置
  183. formConfig.forEach((item) => {
  184. if (item.config) {
  185. // 合并配置项
  186. config = { ...config, ...item.config }
  187. // 处理每个配置项
  188. Object.keys(item.config).forEach(key => {
  189. const currentConfig = item.config[key];
  190. let value = formData[key];
  191. // 如果formFields中已经有值,保持原值(用户输入或之前设置的值)
  192. if (formFields[key] !== null &&
  193. formFields[key] !== undefined &&
  194. formFields[key] !== ''
  195. // typeof formFields[key] !== 'object'
  196. ) {
  197. // 保留原值,不使用formData中的值
  198. result[key] = formFields[key];
  199. } else {
  200. // 使用formData中的值
  201. result[key] = value;
  202. }
  203. // 处理特殊字段 - "其他"字段
  204. if (currentConfig.otherCode) {
  205. const { otherCode,type } = currentConfig;
  206. //如果是更新的话,优先使用formFields中的值
  207. if (update) {
  208. result[otherCode] = formFields[otherCode] || formData[otherCode] || '';
  209. } else {
  210. result[otherCode] = formData[otherCode] || formFields[otherCode] || '';
  211. }
  212. config[otherCode] = { label: "template.common.other",parentType:type, parentKey: key, type: "input", fillType: currentConfig.fillType }
  213. }
  214. if (currentConfig.subKey) {
  215. const { subKey } = currentConfig;
  216. if (update) {
  217. result[subKey] = formFields[subKey] || formData[subKey] || '';
  218. } else {
  219. result[subKey] = formData[subKey] || formFields[subKey] || '';
  220. }
  221. config[subKey] = { label: currentConfig.label, subKey, type: currentConfig.subType, fillType: currentConfig.subFillType || currentConfig.fillType, selectTo: currentConfig.selectTo }
  222. }
  223. // 检查compareTo字段
  224. if (currentConfig.compareTo && formData[currentConfig.compareTo] && result[key]) {
  225. const compareToValue = formData[currentConfig.compareTo];
  226. const currentValue = result[key];
  227. this.compareFieldsIsEqual(currentValue, compareToValue, key)
  228. }
  229. // 检查compareTo字段
  230. if (currentConfig.subCompareTo && formData[currentConfig.subCompareTo] && result[currentConfig.subKey]) {
  231. const compareToValue = formData[currentConfig.subCompareTo];
  232. const currentValue = result[currentConfig.subKey];
  233. this.compareFieldsIsEqual(currentValue, compareToValue, currentConfig.subKey)
  234. }
  235. });
  236. // 处理可能存在的直接otherCode字段
  237. if (item.config?.otherCode) {
  238. config[item.config?.otherCode] = item.config?.otherCode;
  239. }
  240. }
  241. });
  242. // 处理selectInfo_开头的字段,步骤表单需要保留selectInfo_开头的字段
  243. const selectInfoKeys = Object.keys(formData).filter(key => key.startsWith("selectInfo_"));
  244. selectInfoKeys.forEach(key => {
  245. result[key] = formData[key];
  246. })
  247. // 更新表单字段
  248. this.formFields = result;
  249. this.allFieldsConfig = config;
  250. },
  251. //比较值是否相等
  252. compareFieldsIsEqual(currentValue, compareToValue, key) {
  253. if (!currentValue || !compareToValue) return;
  254. // 如果当前值与compareTo字段的值不相等,则设置橙色背景
  255. if (isEqual(currentValue, compareToValue)) {
  256. // 如果相等,移除橙色背景(如果之前设置了的话)
  257. this.$set(this.orangeBgFields, key, false);
  258. } else {
  259. this.$set(this.orangeBgFields, key, true);
  260. }
  261. },
  262. //判断是否禁用
  263. getDisabled() {
  264. const { item } = this;
  265. const { fillType } = item;
  266. if (item.hasOwnProperty("disabled")) {
  267. return item.disabled
  268. } else {
  269. if (fillType === "actFill") {//当模板状态是实际填写时,只有当fillType是actFill时才能填写
  270. return this.templateFillType !== "actFill"
  271. } else if (fillType === "preFill") {//当模板状态是预填写时,只有当fillType是preFill才能填写
  272. return this.templateFillType !== "preFill"
  273. } else {
  274. return true
  275. }
  276. }
  277. },
  278. // 表单数据校验
  279. validateFormData() {
  280. const { formFields, allFieldsConfig } = this;
  281. const errors = [];
  282. // 清空之前的错误状态
  283. this.errors = {};
  284. for (const key in allFieldsConfig) {
  285. const o = allFieldsConfig[key];
  286. if (o.otherCode) {//
  287. if (o.type === "select") {
  288. const isSelectedOther = this.isShowOther(formFields[key]);
  289. if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
  290. formFields[o.otherCode] = "";
  291. }
  292. } else if (o.subType === "select") {
  293. const isSelectedOther = this.isShowOther(formFields[o.subKey]);
  294. if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
  295. formFields[o.otherCode] = "";
  296. }
  297. }else if(o.type === "radioAndOther"){
  298. const isSelectedOther = this.isShowOtherByRadioAndOther(formFields[key]);
  299. if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段
  300. formFields[o.otherCode] = "";
  301. }
  302. }
  303. }
  304. if(o.type === "attachment"){
  305. const attValue = formFields[key];
  306. if(!attValue || attValue == "[]"){
  307. errors.push({
  308. field: key,
  309. label: o.label,
  310. error: "请上传附件"
  311. });
  312. this.$set(this.errors, key, true);
  313. }
  314. }
  315. if (this.isValueEmpty(formFields[key])) {
  316. // 其他字段需要判断是否显示再校验
  317. if (o.label === "template.common.other" && !this.isShowOther(formFields[o.parentKey]) && o.parentType !== "radioAndOther") {
  318. continue
  319. }
  320. if (o.type === "radioAndOther" &&o.label === "template.common.other" && !this.isShowOtherByRadioAndOther(formFields[o.parentKey])) {
  321. continue
  322. }
  323. //span的字段不校验
  324. if (o.type === "span" || o.type === "text" || o.type === "button") {
  325. continue
  326. }
  327. if (o.fillType === this.templateFillType && !o.disabled) {
  328. let prefix = "";
  329. if (o.type === "input" || o.type === "inputNumber" || o.type === "textarea") {
  330. prefix = "填写";
  331. } else {
  332. prefix = "选择";
  333. }
  334. const errorItem = {
  335. field: key,
  336. label: o.label,
  337. error: `${prefix}${o.label}`
  338. };
  339. errors.push(errorItem);
  340. this.$set(this.errors, key, true);
  341. }
  342. }
  343. }
  344. console.log(errors, "errors")
  345. return {
  346. valid: errors.length === 0,
  347. errors: errors
  348. };
  349. },
  350. // 判断值是否为空
  351. isValueEmpty(value) {
  352. if (value === null || value === undefined || value === '') {
  353. return true;
  354. }
  355. if (typeof value === 'string' && value.trim() === '') {
  356. return true;
  357. }
  358. if (Array.isArray(value) && value.length === 0) {
  359. return true;
  360. }
  361. return false;
  362. },
  363. getFormData() {
  364. // 同时执行数据校验和子组件校验
  365. const validateResult = this.validateFormData();
  366. const subComponentValidateResult = this.validateSubComponents();
  367. // const subComponentValidateResult = {valid: true, error: ''};
  368. return new Promise((resolve, reject) => {
  369. if (validateResult.valid && subComponentValidateResult.valid) {
  370. resolve(this.formFields);
  371. } else if (!validateResult.valid) {
  372. // this.$message.error("表单内容未填完,请填写后再提交");
  373. reject(validateResult.errors[0].error);
  374. } else {
  375. reject(subComponentValidateResult.error);
  376. }
  377. });
  378. },
  379. // 子组件校验钩子方法,子组件可以重写此方法来添加额外的校验逻辑
  380. validateSubComponents() {
  381. return {
  382. valid: true,
  383. error: ''
  384. };
  385. },
  386. //直接获取表单数据,不做校验
  387. getFilledFormData() {
  388. return this.formFields;
  389. },
  390. getFormDataByKey(key) {
  391. return this.formFields[key];
  392. },
  393. onBlur(key, val) {
  394. // compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色
  395. this.onValueChangeCompareTo(key, val);
  396. this.$emit("blur", { key, value: val, ...this.formFields });
  397. },
  398. onValueChangeCompareTo(key, val, compKey) {
  399. // compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色
  400. const currentFieldConfig = this.allFieldsConfig[key];
  401. if (currentFieldConfig && currentFieldConfig.fillType === "actFill" && (currentFieldConfig.compareTo || compKey)) {
  402. const compareToKey = compKey || currentFieldConfig.compareTo;
  403. const compareToValue = this.formFields[compareToKey];
  404. this.compareFieldsIsEqual(val, compareToValue, key);
  405. }
  406. },
  407. onAttachmentChange(key, val) {
  408. this.formFields[key] = val;
  409. // 清除该表单项的错误状态
  410. if (this.errors[key]) {
  411. this.$set(this.errors, key, false);
  412. }
  413. // 如果是checkboxList类型,需要处理otherValues
  414. if (val && typeof val === 'object' && val.otherValues) {
  415. // 将otherValues中的每个值也保存到formFields中
  416. Object.keys(val.otherValues).forEach(otherCode => {
  417. this.formFields[otherCode] = val.otherValues[otherCode];
  418. });
  419. }
  420. },
  421. //复制
  422. onCopy(config, key) {
  423. const { formFields } = this;
  424. if (config.copyFrom) {
  425. formFields[key] = formFields[config.copyFrom];
  426. this.onBlur(key, formFields[key]);
  427. }
  428. },
  429. resetRecord(key) {
  430. this.formFields = { ...this.formFields, ...this.oldFormFields };
  431. this.oldFormFields = {};
  432. },
  433. }
  434. }