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

670 lines
24 KiB

  1. import moment from 'moment'
  2. import { getLatestSn, getLatestSnArr } from '@/api/template';
  3. import { isValueEmpty, getStringWidth } from '@/utils/index';
  4. import { isCommonUnit } from "@/utils/conTools";
  5. import { sj_subpackage, sj_startConfiguration, sj_configurationCompleted } from '@/api/business/sj/sj';
  6. import { convertConcentration } from "@/utils/conConverter";//浓度单位转换
  7. import { volumeConverter } from "@/utils/volConverter";//体积单位转换
  8. import * as XLSX from 'xlsx'
  9. import { EventBus } from "@/utils/eventBus";
  10. export default {
  11. dicts: [
  12. 'business_pztj',
  13. 'business_cctj',
  14. 'business_nddw',
  15. 'business_tjdw',
  16. 'business_zldw',
  17. 'business_yxqdw',
  18. 'business_rqcz',
  19. 'business_sp_jmdyzqdyp', //色谱-编号-准确度与精密度
  20. 'business_sp_nbgzy', //色谱-编号-内标工作液
  21. 'business_sp_zkgzy', //色谱-编号-质控工作液
  22. 'business_sp_bqgzy', //色谱-编号-标曲工作液
  23. 'business_sp_bzqxzkypzbb', //色谱-编号-标准曲线/质控样品制备表
  24. 'business_sp_tqhsl', //色谱-编号-提取回收率
  25. 'business_sp_qxwdx', //色谱-编号-全血稳定性
  26. 'business_sp_cbyhgzywdx', //色谱-编号-储备液和工作液稳定性
  27. 'business_sp_rxjzxy', //色谱-编号-溶血基质效应
  28. 'business_sp_jzxy', //色谱-编号-基质效应
  29. 'business_sp_xzxytyx', //色谱-编号-选择性与特异性
  30. 'business_sp_zdybs', //色谱-编号-最大样本数
  31. 'business_sp_xskkx', //色谱-编号-稀释可靠性
  32. 'business_sp_cbydb', //色谱-编号-储备液对比
  33. 'business_pcr_gzy', // PCR-编号-工作液
  34. 'business_lba_jg', // LBA006-结果
  35. 'business_cftj', // 存放条件
  36. 'business_yplx', // 样品类型
  37. 'business_sydd', // 毒理-Ames实验地点
  38. 'business_dl_ameswrqk', // 毒理-Ames污染情况
  39. 'business_dl_amescltj', // 毒理-Ames处理条件
  40. 'business_dl_amesbjjt', // 毒理-Ames背景菌苔
  41. 'business_dl_amescdqk', // 毒理-Ames沉淀情况
  42. 'business_dl_xbmc', // 毒理-Ames细胞名称
  43. 'business_dl_qsxjbltj', // 毒理-暴露条件
  44. 'business_rylx', // 溶液类型
  45. 'business_xbzb', // 细胞组别
  46. 'business_xblx', // 细胞类型
  47. 'business_pytj', // 毒理-培养条件
  48. 'business_fstj', // 毒理-复苏条件
  49. 'business_dsfs', //动技-递送方式
  50. 'business_knj', //动技-抗凝剂
  51. 'business_fhlr', //动技-复核内容
  52. 'business_fhfw', //动技-复核范围
  53. 'business_dwzs', // 动物种属
  54. 'business_cjdd', // 采集地点
  55. 'business_zpdd', // 制片地点
  56. ],
  57. props: {
  58. templateData: {
  59. type: Object,
  60. default: () => { }
  61. }
  62. },
  63. watch: {
  64. templateData: {
  65. immediate: true,
  66. deep: true,
  67. handler(v) {
  68. if (v) {
  69. const {
  70. studySubjectId,
  71. studyId,
  72. studyMc,
  73. studySn,
  74. templateMc,
  75. templateMcEn,
  76. templateId,
  77. templateSn,
  78. startDate,
  79. bdmc,
  80. endDate,
  81. id
  82. } = v
  83. if (v.resource) {
  84. //type 类型:1:试剂;3:给药制剂;5:麻精药;7:供试品
  85. //试验试剂信息 试剂
  86. // this.resource = _.filter(JSON.parse(v.resource), function (o) {
  87. // return o.type == 1 || o.elnType == 1
  88. // })
  89. // //试验物资信息 供试品、给药制剂、麻精药
  90. // this.resourceWz = _.filter(JSON.parse(v.resource), function (o) {
  91. // return o.type == 3 || o.type == 5 || o.type == 7 || o.elnType == 3|| o.elnType == 5 || o.elnType == 7
  92. // })
  93. //试验试剂信息
  94. this.resourceSj = _.filter(JSON.parse(v.resource), function (o) {
  95. return o.type == 1 || o.elnType == 1
  96. })
  97. //供试品信息
  98. this.resourceGsp = _.filter(JSON.parse(v.resource), function (o) {
  99. return o.type == 7 || o.elnType == 7
  100. })
  101. //给药制剂信息
  102. this.resourceGyzj = _.filter(JSON.parse(v.resource), function (o) {
  103. return o.type == 3 || o.elnType == 3
  104. })
  105. //麻精药信息
  106. this.resourceMjy = _.filter(JSON.parse(v.resource), function (o) {
  107. return o.type == 5 || o.elnType == 5
  108. })
  109. }
  110. if (v.yqResource) {
  111. //仪器信息
  112. this.yqResource = JSON.parse(v.yqResource)
  113. }
  114. this.product = v.product || null
  115. if (v.bdnr) {
  116. this.formData = {
  117. ...JSON.parse(v.bdnr),
  118. studySubjectId,
  119. studyId,
  120. studyMc,
  121. studySn,
  122. templateMc,
  123. templateMcEn,
  124. templateId,
  125. templateSn,
  126. startDate,
  127. bdmc,
  128. endDate,
  129. id
  130. }
  131. } else {
  132. this.formData = {
  133. studySubjectId,
  134. studyId,
  135. studyMc,
  136. studySn,
  137. templateMc,
  138. templateMcEn,
  139. templateId,
  140. templateSn,
  141. startDate,
  142. bdmc,
  143. endDate,
  144. id
  145. }
  146. }
  147. const { effectivePeriod, effectivePeriodUnit, expireDate } =
  148. this.formData
  149. //实际填报的时候,如果有了开始时间,并且有有效周期,但是没有失效日,就计算失效日为开始时间+有效周期
  150. if (
  151. startDate &&
  152. this.fillType === 'actFill' &&
  153. effectivePeriod &&
  154. effectivePeriodUnit &&
  155. !expireDate
  156. ) {
  157. const start = moment(startDate)
  158. const unit = effectivePeriodUnit === '天' ? 'days' : 'hours'
  159. const end = start
  160. .add(Number(effectivePeriod), unit)
  161. .format('YYYY-MM-DD HH:mm:ss')
  162. this.formData = { ...this.formData, expireDate: end }
  163. }
  164. console.log(this.formData, 'formData from templateData')
  165. this.setTemplateData(v)
  166. }
  167. }
  168. }
  169. },
  170. data() {
  171. return {
  172. formData: {},
  173. templateDetail: {},
  174. product: null,//产物:1:试剂;3:给药制剂;5:麻精药
  175. resource: [], //试验试剂信息--弃用
  176. resourceWz: [], //物资信息--弃用
  177. resourceSj: [],//试验试剂信息
  178. resourceGsp: [],//供试品信息
  179. resourceGyzj: [],//给药制剂信息
  180. resourceMjy: [],//麻精药信息
  181. yqResource: [], //仪器信息
  182. jcbList: [], //检测板信息
  183. xbxj: [], //细胞细菌信息
  184. resourceTmp: [],//试验试剂信息提交用
  185. yqResourceTmp: [], //仪器信息提交用
  186. jcbListTmp: [], //检测板信息提交用
  187. xbxjTmp: [],//细胞细菌信息提交用
  188. sjColumns: [
  189. { label: 'template.common.reagentName', prop: "mc" },//名称
  190. { label: 'template.common.reagentCode', prop: "bh" },//编号
  191. { label: 'template.common.reagentNo', prop: "ph" },//批号 试剂,供试品才有
  192. { label: 'template.common.concentration', prop: "ndz" },//浓度
  193. { label: 'template.common.source', prop: "ly" },//来源
  194. { label: 'template.common.reagentExpireDate', prop: "sxrq" },//失效日期
  195. ],
  196. gspColumns: [
  197. { label: 'template.common.wzName', prop: "mc" },//名称
  198. { label: 'template.common.wzCode', prop: "bh" },//编号
  199. { label: 'template.common.reagentNo', prop: "ph" },//批号 试剂,供试品才有
  200. { label: 'template.common.wzSource', prop: "ly" },//来源
  201. { label: 'template.common.wzConcentration', prop: "ndz" },//浓度
  202. { label: 'template.common.wzExpireDate', prop: "sxrq" },//失效日期
  203. ],
  204. gyzjColumns: [
  205. { label: 'template.common.wzName', prop: "mc" },//名称
  206. { label: 'template.common.wzCode', prop: "bh" },//编号
  207. { label: 'template.common.wzSource', prop: "ly" },//来源
  208. { label: 'template.common.wzConcentration', prop: "ndz" },//浓度
  209. { label: 'template.common.wzExpireDate', prop: "sxrq" },//失效日期
  210. ],
  211. mjyColumns: [
  212. { label: 'template.common.wzName', prop: "mc" },//名称
  213. { label: 'template.common.wzCode', prop: "bh" },//编号
  214. { label: 'template.common.wzSource', prop: "ly" },//来源
  215. { label: 'template.common.wzConcentration', prop: "ndz" },//浓度
  216. { label: 'template.common.wzExpireDate', prop: "sxrq" },//失效日期
  217. ],
  218. //弃用
  219. sysjColumns: [
  220. { label: 'template.common.reagentName', prop: "mc" },//名称
  221. { label: 'template.common.reagentCode', prop: "bh" },//编号
  222. { label: 'template.common.reagentNo', prop: "ph" },//批号 试剂,供试品才有
  223. { label: 'template.common.concentration', prop: "ndz" },//浓度
  224. { label: 'template.common.source', prop: "ly" },//来源
  225. { label: 'template.common.reagentExpireDate', prop: "sxrq" },//失效日期
  226. ],
  227. //弃用
  228. sywzColumns: [
  229. { label: 'template.common.wzName', prop: "mc" },//名称
  230. { label: 'template.common.wzCode', prop: "bh" },//编号
  231. { label: 'template.common.wzSource', prop: "ly" },//来源
  232. { label: 'template.common.wzConcentration', prop: "ndz" },//浓度
  233. { label: 'template.common.wzExpireDate', prop: "sxrq" },//失效日期
  234. ],
  235. yqColumns: [
  236. { label: 'template.common.instrumentName', prop: "mc" },//仪器名称
  237. { label: 'template.common.instrumentModel', prop: "xh" },//仪器型号
  238. { label: 'template.common.instrumentCode', prop: "bh" },//仪器编号
  239. { label: 'template.common.nextTestDate', prop: "jzrq" },//下次测试/校准/检定日期
  240. ],
  241. }
  242. },
  243. mounted() { },
  244. unmounted() {
  245. this.setTemplateData({})
  246. },
  247. methods: {
  248. // 只是更新已填写的表单数据,不触发校验
  249. justUpdateFilledFormData() {
  250. const params = {
  251. type: "fieldChanged",
  252. newRecord: null,
  253. resourceList: null,
  254. }
  255. EventBus.$emit('onModifyRecord', params,)
  256. },
  257. //试剂弹窗确认前
  258. onBeforeReagentSubmit(data) {
  259. const { selectData, callback, key, formFields } = data;
  260. const { subTargetStartSolution } = formFields;
  261. //判断选择的浓度单位和预制的浓度单位是否一致
  262. if (key === "subStartSolution" && !isCommonUnit(selectData.row.nddw, [subTargetStartSolution])) {//选择起始源溶液需要同步更新table的变更记录。
  263. callback.prevent('浓度单位与预制不符,请重新选择或申请废止并重新预制。');
  264. }
  265. },
  266. getFormDataByTemplateData() {
  267. let o = {};
  268. const { bdnr } = this.templateData
  269. if (bdnr) {
  270. o = JSON.parse(bdnr)
  271. }
  272. return o;
  273. },
  274. //开始配置
  275. //postData: {bh: '123456'}
  276. async startConfigRequest(postData) {
  277. const res = await sj_startConfiguration(postData)
  278. if (res.code === 200) {
  279. this.$message.success('开始配置成功')
  280. } else {
  281. this.$message.error('开始配置失败')
  282. }
  283. },
  284. //完成配置
  285. async configCompleteRequest(postData) {
  286. const res = await sj_configurationCompleted(postData)
  287. if (res.code === 200) {
  288. this.$message.success('完成配置成功')
  289. } else {
  290. this.$message.error('完成配置失败')
  291. }
  292. },
  293. //分装
  294. async subPackageRequest(postData) {
  295. const res = await sj_subpackage(postData)
  296. if (res.code === 200) {
  297. this.$message.success('分装成功')
  298. } else {
  299. this.$message.error('分装失败')
  300. }
  301. },
  302. //获取打印配置
  303. getBasePrintConfig(data = {}) {
  304. const { printCode, type, row = {} } = data;
  305. const { stepStorageCondition, startDate, expireDate } = this.formData;;
  306. const { nickName, name } = this.$store.getters;
  307. const lang = this.$i18n.locale;
  308. const printConfig = {
  309. "品名": "暂时还不知道品名是哪个字段",
  310. "存储条件": stepStorageCondition,
  311. "配制日期": moment(startDate).format("YYYY-MM-DD"),
  312. "有效期至": moment(expireDate).format("YYYY-MM-DD HH:mm"),
  313. "配置者": lang === "zh_CN" ? nickName : name,
  314. //type==="subPackage"从分装打印过来的,
  315. //type==="row" 从列表上点过来的
  316. "编号": type === "subPackage" ? printCode : (row.targetSolutionCode + row.subTargetSolutionCode),
  317. }
  318. return printConfig
  319. },
  320. async getLatestSn(count = 1) {
  321. const res = await getLatestSn({ count })
  322. if (res.code === 200) {
  323. return res.data
  324. }
  325. return []
  326. },
  327. //获取最新的多个编号
  328. async getLatestSnArr(params) {
  329. const res = await getLatestSnArr(params)
  330. if (res.code === 200) {
  331. return res.data
  332. }
  333. return []
  334. },
  335. getResource() {
  336. return this.resourceTmp
  337. },
  338. getYqResource() {
  339. return this.yqResourceTmp
  340. },
  341. getJcbList() {
  342. return this.jcbListTmp
  343. },
  344. getXbxj() {
  345. return this.xbxjTmp
  346. },
  347. //根据ref数组获取直接formData
  348. getFilledFormDataByRefs(refArr = []) {
  349. let result = {}
  350. refArr.map((ref) => {
  351. const refData = this.$refs[ref]?.getFilledFormData() || {}
  352. for (const [key, value] of Object.entries(refData)) {
  353. let index = 0
  354. // 如果当前键是可能重复的字段,且结果对象中已经存在该键,则添加索引后缀
  355. if (
  356. (key === 'headerSelectFields' || key === 'stepTableFormData') &&
  357. result.hasOwnProperty(key)
  358. ) {
  359. // 为重复字段生成带索引的键名,从1开始(因为第一个组件不需要后缀)
  360. const newKey = `${key}_${++index}`
  361. result[newKey] = value
  362. } else {
  363. // 正常合并其他字段
  364. result[key] = value
  365. }
  366. }
  367. })
  368. return result
  369. },
  370. //统一校验form表单是否填写
  371. async validFormFields(refArr = []) {
  372. let result = {}
  373. const refs = refArr.map((ref) => {
  374. let refData = {}
  375. if (this.$refs[ref]) {
  376. if (this.$refs[ref][0]) {
  377. refData = this.$refs[ref][0]?.getFormData() || {}
  378. } else {
  379. refData = this.$refs[ref]?.getFormData() || {}
  380. }
  381. }
  382. return refData
  383. })
  384. const validFormData = await Promise.all(refs).catch((err) => {
  385. // this.$message.error(err);
  386. if (err.errorType && err.errorType === 'step') {
  387. this.$message.error('请添加步骤')
  388. return
  389. }
  390. this.$message.error('表单内容未填完,请填写后再提交')
  391. })
  392. if (validFormData) {
  393. validFormData.forEach((item) => {
  394. for (const [key, value] of Object.entries(item)) {
  395. let index = 0
  396. // 如果当前键是可能重复的字段,且结果对象中已经存在该键,则添加索引后缀
  397. if (
  398. (key === 'headerSelectFields' || key === 'stepTableFormData') &&
  399. result.hasOwnProperty(key)
  400. ) {
  401. // 为重复字段生成带索引的键名,从1开始(因为第一个组件不需要后缀)
  402. const newKey = `${key}_${++index}`
  403. result[newKey] = value
  404. } else {
  405. // 正常合并其他字段
  406. result[key] = value
  407. }
  408. }
  409. })
  410. return result
  411. }
  412. return false
  413. },
  414. //试验配制条件options
  415. getDictOptions(dictType) {
  416. return this.dict.type[dictType] || []
  417. },
  418. setTemplateData(data) {
  419. this.$store.commit('template/SET_TEMPLATE_DATA', data)
  420. },
  421. //统一处理删除行
  422. deleteRow(index, ref) {
  423. if (ref) {
  424. this.$refs[ref].deleteRow(index);
  425. return;
  426. }
  427. this.$refs.stepTableRef.deleteRow(index)
  428. },
  429. //统一处理浓度校验异常
  430. onCommonVerifyNdException(formFields, data) {
  431. const { callback, rowIndex, key, dataSource } = data;
  432. const keys = [
  433. 'actStartSolutionVolume',
  434. 'actDiluentVolume',
  435. ]
  436. if (keys.includes(key)) {
  437. const { targetAcSolution } = formFields;
  438. if (rowIndex === 0) {//第一行的浓度取选择的溶液,
  439. if (isValueEmpty(targetAcSolution)) {
  440. callback.prevent("请先选择起始源溶液")
  441. }
  442. } else {
  443. //非第一行的浓度取上一行的浓度
  444. const prevItem = dataSource[rowIndex - 1]
  445. const prevConcentration = prevItem.actSolutionConcentration;
  446. if (!prevConcentration) {
  447. callback.prevent("请先计算上一行的实际目标溶液浓度")
  448. }
  449. }
  450. }
  451. },
  452. //统一处理blur事件,因为有效周期和过期日期是相关的,所以需要在有效周期失焦时更新过期日期
  453. onHandleBlur(fields) {
  454. const {
  455. key,
  456. codeSTD,
  457. targetStartSolution,
  458. subTargetStartSolution,//预设起始源溶液浓度单位
  459. } = fields
  460. const { startDate } = this.formData
  461. if (key === 'codeSTD') {
  462. //起始编号STD失焦时,更新stepDataSource
  463. const arr = Array.from({ length: codeSTD }, (item, index) => ({
  464. actSolutionVolumePrecision: 3, //小数点精度默认为3
  465. actSolutionConcentrationPrecision: 3, //小数点精度默认为3
  466. targetDiluentVolumePrecision: 3, //小数点精度默认为3
  467. targetStartSolutionVolumePrecision: 3, //小数点精度默认为3
  468. targetSolutionCode: `STD${Number(codeSTD) - index}`
  469. }))
  470. this.$refs.stepTableRef.updateDataSource(arr)
  471. } else if (key === 'targetStartSolution' || key === 'subTargetStartSolution') {
  472. //起始溶液体积失焦时,更新目标溶液预计浓度
  473. const arr = this.$refs.stepTableRef?.getDataSource();
  474. const { headerSelectFields } = this.$refs.stepTableRef?.getFilledFormData();
  475. const params = {
  476. subTargetStartSolution,
  477. headerSelectFields
  478. }
  479. arr.forEach((item, rowIndex) => {
  480. this.updateTargetStartSolutionVolume(
  481. item,
  482. targetStartSolution,
  483. params
  484. )
  485. })
  486. }
  487. },
  488. //批量更新目标起始源溶液体积
  489. batchUpdateTargetStartSolutionVolume(arr, startConcentration, params) {
  490. arr.forEach((item, rowIndex) => {
  491. this.updateTargetStartSolutionVolume(
  492. item,
  493. startConcentration,
  494. params
  495. )
  496. })
  497. },
  498. //统一处理table失焦事件
  499. onHandleTableBlur(params) {
  500. const { rowIndex, colKey, value, item, dataSource, headerSelectFields } = params
  501. if (
  502. colKey === 'targetSolutionVolume' ||
  503. colKey === 'targetSolutionConcentration' ||
  504. colKey === 'targetStartSolutionVolumePrecision' ||
  505. colKey === 'targetDiluentVolumePrecision'
  506. ) {
  507. const volume =
  508. this.$refs.stepFormPackageRef?.getFormDataByKey(
  509. 'targetStartSolution'
  510. )
  511. const subTargetStartSolution =
  512. this.$refs.stepFormPackageRef?.getFormDataByKey(
  513. 'subTargetStartSolution'
  514. )
  515. const params = {
  516. subTargetStartSolution: subTargetStartSolution,
  517. headerSelectFields
  518. }
  519. if (isValueEmpty(volume)) {
  520. this.$message.error('请先选择预设起始源溶液浓度')
  521. } else {
  522. this.updateTargetStartSolutionVolume(item, volume, params)
  523. }
  524. } else if (
  525. colKey === 'actStartSolutionVolume' ||
  526. colKey === 'actDiluentVolume'
  527. ) {
  528. //实际起始溶液体积和实际目标溶液体积
  529. const { targetAcSolution, subTargetAcSolutionUnit } =
  530. this.$refs.stepFormPackageRef?.getFilledFormData() //获取实际起始溶液浓度
  531. const { headerSelectFields } = this.$refs.stepTableRef?.getFilledFormData();
  532. const p = {
  533. targetStartSolutionUnit: subTargetAcSolutionUnit,
  534. headerSelectFields
  535. }
  536. let initNd = 0;
  537. if (rowIndex === 0) {
  538. initNd = targetAcSolution;
  539. } else {
  540. initNd = dataSource[rowIndex - 1].actSolutionConcentration;
  541. }
  542. if (isValueEmpty(initNd)) {
  543. this.$message.error('请先选择起始源溶液')
  544. return
  545. } else {
  546. const volResult = this.updateSjmbrynd(item, initNd, p)
  547. if (!volResult) {
  548. return
  549. }
  550. this.$refs.stepTableRef?.updateDataSourceByRowIndex(rowIndex, { actSolutionVolume: volResult.actVol, actSolutionConcentration: volResult.actNd }, "blur")
  551. }
  552. }
  553. },
  554. //计算目标溶液浓度
  555. calcNd(item, targetAcSolution, params) {
  556. console.log(params, "ppp")
  557. // debugger
  558. //targetStartSolutionUnit(实际起始源溶液浓度单位)
  559. const { targetStartSolutionUnit, headerSelectFields } = params;
  560. //actStartSolutionVolumeUnit(实际起始源溶液体积单位)actSolutionVolumeUnit(实际目标溶液体积单位)
  561. //actDiluentVolumeUnit(实际稀释液体积单位)actSolutionConcentrationUnit(实际目标溶液浓度单位)
  562. const { actStartSolutionVolumeUnit, actSolutionVolumeUnit, actDiluentVolumeUnit, actSolutionConcentrationUnit } = headerSelectFields;
  563. //实际源溶液浓度÷(实际终体积÷源溶液加入体积);
  564. const precision = item.actSolutionConcentrationPrecision
  565. const volPrecision = item.actSolutionVolumePrecision;
  566. //实际稀释液体积
  567. const actDiluentVolume = item.actDiluentVolume
  568. //实际起始源溶液体积
  569. const actStartSolutionVolume = item.actStartSolutionVolume
  570. if (isValueEmpty(actStartSolutionVolume) || isValueEmpty(actDiluentVolume) || isValueEmpty(targetStartSolutionUnit)) {
  571. return false
  572. }
  573. const converActDiluentVolume = volumeConverter.convert(actDiluentVolume + actDiluentVolumeUnit, actSolutionVolumeUnit)
  574. const converActStartSolutionVolume = volumeConverter.convert(actStartSolutionVolume + actStartSolutionVolumeUnit, actSolutionVolumeUnit)
  575. //实际源溶液加入体积+实际稀释液加入体积
  576. const actVol = (
  577. Number(converActDiluentVolume) + Number(converActStartSolutionVolume)
  578. ).toFixed(volPrecision)
  579. const targetStartVolUnit = actSolutionConcentrationUnit.split("/")[1];//先按照预设目标溶液浓度的单位标准
  580. const converActVol = volumeConverter.convert(actVol + actSolutionVolumeUnit, targetStartVolUnit)
  581. const converActDiluentVolume1 = volumeConverter.convert(actStartSolutionVolume + actStartSolutionVolumeUnit, targetStartVolUnit)
  582. const converTargetAcSolution = convertConcentration.convert(targetAcSolution + targetStartSolutionUnit, actSolutionConcentrationUnit)
  583. // 实际目标溶液浓度 = 实际源溶液浓度÷(实际终体积÷源溶液加入体积);
  584. const actNd = (
  585. parseFloat(converTargetAcSolution) / (
  586. parseFloat(converActVol) / parseFloat(converActDiluentVolume1)
  587. )
  588. ).toFixed(precision)
  589. const nd = actNd === 'Infinity' ? 0 : Number(actNd)
  590. console.log(actNd, targetAcSolution, actStartSolutionVolume, actVol, "actNd")
  591. // item.actSolutionConcentration = actNd === 'Infinity' ? 0 : actNd
  592. return { actVol: Number(actVol), actNd: nd }
  593. },
  594. //计算并更新实际目标溶液浓度 先计算实际目标溶液体积再计算实际目标溶液浓度
  595. updateSjmbrynd(item, targetAcSolution, params) {
  596. return this.calcNd(item, targetAcSolution, params)
  597. },
  598. //更新起始溶液体积时,计算预设起始溶液体积和预设稀释液体积
  599. updateTargetStartSolutionVolume(item, volume, unitParams) {
  600. const precision = item.targetStartSolutionVolumePrecision || 0
  601. const concentration = item.targetSolutionConcentration
  602. const targetVolume = item.targetSolutionVolume
  603. const { subTargetStartSolution, headerSelectFields } = unitParams
  604. const { targetSolutionConcentrationUnit, targetSolutionVolumeUnit, targetStartSolutionVolumeUnit, targetDiluentVolumeUnit } = headerSelectFields
  605. if (
  606. isValueEmpty(concentration) ||
  607. isValueEmpty(targetVolume) ||
  608. isValueEmpty(subTargetStartSolution) ||
  609. isValueEmpty(targetSolutionConcentrationUnit) ||
  610. isValueEmpty(targetSolutionVolumeUnit) ||
  611. isValueEmpty(targetStartSolutionVolumeUnit) ||
  612. isValueEmpty(targetDiluentVolumeUnit)
  613. ) {
  614. return;
  615. }
  616. const targetStartVolUnit = targetSolutionConcentrationUnit.split("/")[1];//先按照预设目标溶液浓度的单位标准
  617. //将起始溶液浓度转换为和预设目标溶液浓度一样的单位再计算;
  618. const converStartCon = convertConcentration.convert(volume + subTargetStartSolution, targetSolutionConcentrationUnit)
  619. //将预设目标溶液体积转换为和预设目标溶液浓度单位的分母一样的单位再计算;如:预设目标溶液浓度单位为mg/mL,预设目标溶液体积单位为uL,则将预设目标溶液体积转换为mL
  620. const convertTargetVol = volumeConverter.convert(targetVolume + targetSolutionVolumeUnit, targetStartVolUnit)
  621. //预设起始溶液体积:(目标溶液预计浓度 乘以 目标溶液预计体积)除以 起始溶液浓度
  622. const result = Number((concentration * convertTargetVol) / converStartCon)
  623. //根据预设起始溶液体积单位转换计算后的数据
  624. const convertYsVol = volumeConverter.convert(result + targetStartVolUnit, targetStartSolutionVolumeUnit)
  625. item.targetStartSolutionVolume = Number(convertYsVol.toFixed(
  626. precision
  627. ))
  628. // this.$refs.stepTableRef.updateDataSourceByRowIndex(rowIndex, { targetStartSolutionVolume: result });
  629. if (targetVolume) {
  630. //预设稀释液体积:目标溶液预计体积 减去 源溶液预计体积;
  631. const precision1 = item.targetDiluentVolumePrecision || 0;
  632. //将预设目标溶液体积转换为和预设起始溶液体积单位一样的单位再计算;
  633. const convertTargetVol1 = volumeConverter.convert(targetVolume + targetSolutionVolumeUnit, targetStartSolutionVolumeUnit)
  634. const result1 = (convertTargetVol1 - convertYsVol)
  635. item.targetDiluentVolume = Number(volumeConverter.convert(result1 + targetStartSolutionVolumeUnit, targetDiluentVolumeUnit).toFixed(precision1))
  636. // this.$refs.stepTableRef.updateDataSourceByRowIndex(rowIndex, { targetDiluentVolume: result1 });
  637. }
  638. },
  639. // 导出excel模板
  640. exportExcel(headerArray, title = '导出模板') {
  641. this.$modal.loading()
  642. const ws = XLSX.utils.aoa_to_sheet([headerArray]);
  643. const colWidths = headerArray.map(cell => getStringWidth(cell) + 2);
  644. ws['!cols'] = colWidths.map(width => ({ wch: width }));
  645. const wb = XLSX.utils.book_new();
  646. XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
  647. XLSX.writeFile(wb, `${title}.xlsx`);
  648. this.$modal.closeLoading()
  649. },
  650. }
  651. }