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

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