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

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