|
|
@@ -0,0 +1,760 @@
|
|
|
+<!--该组件实际差值和实际偏倚有正负值-->
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <div v-if="show" class="reagentChange">
|
|
|
+ <el-row type="flex">
|
|
|
+ <el-col class="button">
|
|
|
+ <div class="title">平行实验/留样再测</div>
|
|
|
+ <div v-if="nodeId === 'Activity_0xkc1ji' || readonly" />
|
|
|
+ <div v-else>
|
|
|
+ <span style="color: red; margin-right: 20px; font-size: 16px"
|
|
|
+ >注意:手动计算与导入不可混用</span
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="mini"
|
|
|
+ icon="ibps-icon-add"
|
|
|
+ @click="handleAdd"
|
|
|
+ >
|
|
|
+ 添加</el-button
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="mini"
|
|
|
+ icon="ibps-icon-copy"
|
|
|
+ @click="handleCopy"
|
|
|
+ >
|
|
|
+ 复制</el-button
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ type="danger"
|
|
|
+ size="mini"
|
|
|
+ icon="ibps-icon-remove"
|
|
|
+ @click="handleDelete"
|
|
|
+ >
|
|
|
+ 删除</el-button
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ type="warning"
|
|
|
+ size="mini"
|
|
|
+ icon="ibps-icon-calculator"
|
|
|
+ @click="computedResult"
|
|
|
+ >计算</el-button
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="mini"
|
|
|
+ icon="ibps-icon-download"
|
|
|
+ @click="handleDownload"
|
|
|
+ >模版下载</el-button
|
|
|
+ >
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="mini"
|
|
|
+ icon="ibps-icon-import"
|
|
|
+ @click="handleImport"
|
|
|
+ >导入</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row type="flex">
|
|
|
+ <el-col>
|
|
|
+ <el-table
|
|
|
+ ref="reagent"
|
|
|
+ :data="reagentDataFilter"
|
|
|
+ :span-method="spanMethod"
|
|
|
+ @selection-change="handleSelectionChange"
|
|
|
+ >
|
|
|
+ <el-table-column type="selection" width="55" />
|
|
|
+ <el-table-column label="检验项目" prop="jianCeXiangMu" />
|
|
|
+ <el-table-column label="浓度" prop="nongDu" width="100">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-input
|
|
|
+ v-if="!disabled"
|
|
|
+ v-model="row.nongDu"
|
|
|
+ size="mini"
|
|
|
+ placeholder="请输入"
|
|
|
+ />
|
|
|
+ <span v-else>{{ row.nongDu || '/' }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="样品编号" prop="biaoBenHao" width="100">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-input
|
|
|
+ v-if="!disabled"
|
|
|
+ v-model="row.biaoBenHao"
|
|
|
+ size="mini"
|
|
|
+ placeholder="请输入"
|
|
|
+ />
|
|
|
+ <span v-else>{{ row.biaoBenHao || '/' }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="旧试剂测得结果"
|
|
|
+ prop="jiuJieGuo"
|
|
|
+ width="130"
|
|
|
+ >
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-input
|
|
|
+ v-if="!disabled"
|
|
|
+ v-model="row.jiuJieGuo"
|
|
|
+ :min="0"
|
|
|
+ size="mini"
|
|
|
+ placeholder="请输入"
|
|
|
+ :type="isCb ? 'text' : 'number'"
|
|
|
+ />
|
|
|
+ <span v-else>{{ row.jiuJieGuo || '/' }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="新试剂测得结果"
|
|
|
+ prop="xinJieGuo"
|
|
|
+ width="130"
|
|
|
+ >
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-input
|
|
|
+ v-if="!disabled"
|
|
|
+ v-model="row.xinJieGuo"
|
|
|
+ :min="0"
|
|
|
+ size="mini"
|
|
|
+ placeholder="请输入"
|
|
|
+ :type="isCb ? 'text' : 'number'"
|
|
|
+ />
|
|
|
+ <span v-else>{{ row.xinJieGuo || '/' }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="计算方式" prop="jiSuanFangShi" width="140">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-select
|
|
|
+ v-if="!disabled"
|
|
|
+ v-model="row.jiSuanFangShi"
|
|
|
+ size="mini"
|
|
|
+ placeholder="请选择"
|
|
|
+ >
|
|
|
+ <el-option label="Y-X" value="Y-X" />
|
|
|
+ <el-option label="Y-X/X(%)" value="Y-X/X(%)" />
|
|
|
+ </el-select>
|
|
|
+ <span v-else>{{ row.jiSuanFangShi || '/' }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="实际差值" prop="shiJiChaZhi" />
|
|
|
+ <el-table-column label="实际偏倚" prop="jieGuo" />
|
|
|
+ <el-table-column
|
|
|
+ :label="isHz ? '允许差值' : '限定范围'"
|
|
|
+ prop="zuiXiaoFanWei"
|
|
|
+ width="110"
|
|
|
+ >
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-input
|
|
|
+ v-if="!disabled"
|
|
|
+ v-model="row.zuiXiaoFanWei"
|
|
|
+ size="mini"
|
|
|
+ placeholder="请输入"
|
|
|
+ type="number"
|
|
|
+ />
|
|
|
+ <span v-else>{{ row.zuiXiaoFanWei || '/' }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="允许偏倚" prop="yunXuPianYi" width="100">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-input
|
|
|
+ v-if="!disabled"
|
|
|
+ v-model="row.yunXuPianYi"
|
|
|
+ size="mini"
|
|
|
+ placeholder="请输入"
|
|
|
+ />
|
|
|
+ <span v-else>{{ row.yunXuPianYi || '/' }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="是否相符" prop="xiangFu" width="80" />
|
|
|
+ <el-table-column label="符合率" prop="biaoZhun" />
|
|
|
+ <el-table-column
|
|
|
+ label="符合率可接受标准"
|
|
|
+ prop="xiangMuFuHeLv"
|
|
|
+ width="140"
|
|
|
+ >
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-select
|
|
|
+ v-if="!disabled"
|
|
|
+ v-model="row.xiangMuFuHeLv"
|
|
|
+ size="mini"
|
|
|
+ placeholder="请选择"
|
|
|
+ @change="handelChange($event, row.jianCeXiangMu)"
|
|
|
+ >
|
|
|
+ <el-option label="≥80%" value="≥80%" />
|
|
|
+ <el-option label="=100%" value="=100%" />
|
|
|
+ </el-select>
|
|
|
+ <span v-else>{{ row.xiangMuFuHeLv || '/' }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="结论" prop="jieLun" />
|
|
|
+ </el-table>
|
|
|
+ <el-pagination
|
|
|
+ layout="total,sizes,prev, pager, next,jumper"
|
|
|
+ :current-page="requestPage.pageNo"
|
|
|
+ :page-size="requestPage.limit"
|
|
|
+ :page-sizes="[10, 15, 20, 30, 50, 100]"
|
|
|
+ :total="reagentData.length"
|
|
|
+ @size-change="handleSizeChange"
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
+ />
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+ <import-table
|
|
|
+ :visible="importTableDialogVisible"
|
|
|
+ title="导入"
|
|
|
+ @close="(visible) => (importTableDialogVisible = visible)"
|
|
|
+ @action-event="handleImportTableActionEvent"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script>
|
|
|
+import importTable from '@/business/platform/form/formrender/dynamic-form/components/import-table'
|
|
|
+import IbpsImport from '@/plugins/import'
|
|
|
+import { downloadFile } from '@/business/platform/file/utils'
|
|
|
+import { cloneDeep } from 'lodash'
|
|
|
+export default {
|
|
|
+ components: {
|
|
|
+ importTable
|
|
|
+ },
|
|
|
+ props: {
|
|
|
+ formData: {
|
|
|
+ type: Object,
|
|
|
+ default: () => {}
|
|
|
+ },
|
|
|
+ readonly: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ params: {
|
|
|
+ type: Object,
|
|
|
+ default: () => {}
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ reagentData: [],
|
|
|
+ copyDialogData: [],
|
|
|
+ disabled: false,
|
|
|
+ ypData: [],
|
|
|
+ nodeId: '',
|
|
|
+ show: true,
|
|
|
+ requestPage: {
|
|
|
+ limit: 20,
|
|
|
+ pageNo: 1
|
|
|
+ },
|
|
|
+ importTableDialogVisible: false,
|
|
|
+ multipleSelection: [],
|
|
|
+ isHz: false,
|
|
|
+ isCb: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ reagentDataFilter() {
|
|
|
+ return this.reagentData.slice(
|
|
|
+ (this.requestPage.pageNo - 1) * this.requestPage.limit,
|
|
|
+ (this.requestPage.pageNo - 1) * this.requestPage.limit +
|
|
|
+ this.requestPage.limit
|
|
|
+ )
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ 'formData.sjghyzjlbbbzb': {
|
|
|
+ handler(value, old) {
|
|
|
+ if (value && value.length) {
|
|
|
+ this.reagentData = value
|
|
|
+ }
|
|
|
+ },
|
|
|
+ immediate: true
|
|
|
+ },
|
|
|
+ reagentData: {
|
|
|
+ handler(value, old) {
|
|
|
+ this.$emit('change-data', 'sjghyzjlbbbzb', value)
|
|
|
+ },
|
|
|
+ deep: true
|
|
|
+ },
|
|
|
+ 'formData.fangAn': {
|
|
|
+ handler(val) {
|
|
|
+ this.showAndHide(val)
|
|
|
+ },
|
|
|
+ immediate: true
|
|
|
+ },
|
|
|
+ 'formData.yunXuPianYi': {
|
|
|
+ handler(val) {
|
|
|
+ this.reagentData.forEach((item) => {
|
|
|
+ const { jianYanXiangMu } = this.formData
|
|
|
+ if (item.jianCeXiangMu === jianYanXiangMu) {
|
|
|
+ item.yunXuPianYi = val
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ immediate: true
|
|
|
+ },
|
|
|
+ 'formData.xianDingFanWei': {
|
|
|
+ handler(val) {
|
|
|
+ this.reagentData.forEach((item) => {
|
|
|
+ const { jianYanXiangMu } = this.formData
|
|
|
+ if (item.jianCeXiangMu === jianYanXiangMu) {
|
|
|
+ item.zuiXiaoFanWei = val
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ const { first = '' } = this.$store.getters.level
|
|
|
+ const { deptList = [] } = this.$store.getters || {}
|
|
|
+ const t1 = deptList.find((i) => i.positionId === first) || {}
|
|
|
+ this.isHz = t1.positionName === '惠州市第三人民医院'
|
|
|
+ this.isCb = t1.positionName === '川北医学院附属医院'
|
|
|
+ // console.log(t1.positionName)
|
|
|
+ this.nodeId = this.params ? this.params.nodeId : ''
|
|
|
+ this.disabled = this.readonly || this.nodeId === 'Activity_0xkc1ji'
|
|
|
+ this.showAndHide(this.formData.fangAn)
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ handelChange(event, jianCeXiangMu) {
|
|
|
+ this.reagentData.forEach((item) => {
|
|
|
+ if (item.jianCeXiangMu == jianCeXiangMu) {
|
|
|
+ item.xiangMuFuHeLv = event
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 新增
|
|
|
+ handleAdd() {
|
|
|
+ if (
|
|
|
+ !this.reagentData ||
|
|
|
+ (this.reagentData && this.reagentData.length === 0)
|
|
|
+ ) {
|
|
|
+ this.disabled = false
|
|
|
+ }
|
|
|
+ const { jianYanXiangMu, yunXuPianYi, xianDingFanWei } = this.formData
|
|
|
+ if (this.disabled && this.reagentData?.length > 0) {
|
|
|
+ return this.$message.warning('导入与手动添加功能不可混用!')
|
|
|
+ }
|
|
|
+ if (!this.formData.jianYanXiangMu) {
|
|
|
+ return this.$message.warning('请选择检验项目')
|
|
|
+ }
|
|
|
+ this.reagentData.push({
|
|
|
+ jianCeXiangMu: jianYanXiangMu,
|
|
|
+ nongDu: '',
|
|
|
+ biaoBenHao: '',
|
|
|
+ jiuJieGuo: '',
|
|
|
+ xinJieGuo: '',
|
|
|
+ jiSuanFangShi: 'Y-X/X(%)',
|
|
|
+ shiJiChaZhi: '',
|
|
|
+ jieGuo: '',
|
|
|
+ zuiXiaoFanWei: xianDingFanWei,
|
|
|
+ yunXuPianYi: yunXuPianYi,
|
|
|
+ xiangFu: '',
|
|
|
+ biaoZhun: '',
|
|
|
+ xiangMuFuHeLv: '≥80%',
|
|
|
+ jieLun: ''
|
|
|
+ })
|
|
|
+ const grouped = this.reagentData.reduce((acc, item) => {
|
|
|
+ const key = item.jianCeXiangMu
|
|
|
+ if (!acc[key]) acc[key] = []
|
|
|
+ acc[key].push(item)
|
|
|
+ return acc
|
|
|
+ }, {})
|
|
|
+ // 先清空数组,再填充新数据(确保 Vue 检测到变化)
|
|
|
+ this.reagentData.splice(
|
|
|
+ 0,
|
|
|
+ this.reagentData.length,
|
|
|
+ ...Object.values(grouped).flat()
|
|
|
+ )
|
|
|
+ console.log(this.reagentData)
|
|
|
+ },
|
|
|
+ // 复制
|
|
|
+ handleCopy() {
|
|
|
+ if (this.multipleSelection.length > 0) {
|
|
|
+ this.reagentData = this.reagentData.concat(
|
|
|
+ cloneDeep(this.multipleSelection)
|
|
|
+ )
|
|
|
+ const grouped = this.reagentData.reduce((acc, item) => {
|
|
|
+ const key = item.jianCeXiangMu
|
|
|
+ if (!acc[key]) acc[key] = []
|
|
|
+ acc[key].push(item)
|
|
|
+ return acc
|
|
|
+ }, {})
|
|
|
+ // 先清空数组,再填充新数据(确保 Vue 检测到变化)
|
|
|
+ this.reagentData.splice(
|
|
|
+ 0,
|
|
|
+ this.reagentData.length,
|
|
|
+ ...Object.values(grouped).flat()
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ this.$message.warning('请选择数据')
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 删除
|
|
|
+ handleDelete() {
|
|
|
+ this.$confirm('确定删除当前选中数据?', '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ if (this.multipleSelection.length > 0) {
|
|
|
+ this.reagentData = this.reagentData.filter(
|
|
|
+ (row) => !this.multipleSelection.includes(row)
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ this.$message.warning('请选择数据')
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ handleSelectionChange(val) {
|
|
|
+ this.multipleSelection = val
|
|
|
+ },
|
|
|
+ handleImport() {
|
|
|
+ this.importTableDialogVisible = true
|
|
|
+ },
|
|
|
+ handleDownload() {
|
|
|
+ downloadFile({
|
|
|
+ id: 'download_sjghdl',
|
|
|
+ fileName: '试剂更换验证定量模板',
|
|
|
+ ext: 'xlsx'
|
|
|
+ })
|
|
|
+ },
|
|
|
+ getColumns() {
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ field_name: 'xiangFu',
|
|
|
+ label: '是否相符',
|
|
|
+ name: 'xiangFu'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field_name: 'jianCeXiangMu',
|
|
|
+ label: '检验项目',
|
|
|
+ name: 'jianCeXiangMu'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field_name: 'nongDu',
|
|
|
+ label: '浓度',
|
|
|
+ name: 'nongDu'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field_name: 'biaoBenHao',
|
|
|
+ label: '样品编号',
|
|
|
+ name: 'biaoBenHao'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field_name: 'jiuJieGuo',
|
|
|
+ label: '旧试剂测得结果',
|
|
|
+ name: 'jiuJieGuo'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field_name: 'xinJieGuo',
|
|
|
+ label: '新试剂测得结果',
|
|
|
+ name: 'xinJieGuo'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field_name: 'shiJiChaZhi',
|
|
|
+ label: '实际差值',
|
|
|
+ name: 'shiJiChaZhi'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field_name: 'jieGuo',
|
|
|
+ label: '实际偏倚',
|
|
|
+ name: 'jieGuo'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field_name: 'zuiXiaoFanWei',
|
|
|
+ label: this.isHz ? '允许差值' : '限定范围',
|
|
|
+ name: 'zuiXiaoFanWei'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field_name: 'yunXuPianYi',
|
|
|
+ label: '允许偏倚',
|
|
|
+ name: 'yunXuPianYi'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field_name: 'biaoZhun',
|
|
|
+ label: '符合率',
|
|
|
+ name: 'biaoZhun'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field_name: 'jieLun',
|
|
|
+ label: '结论',
|
|
|
+ name: 'jieLun'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ field_name: 'xiangMuFuHeLv',
|
|
|
+ label: '符合率可接受标准',
|
|
|
+ name: 'xiangMuFuHeLv'
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ getKeys(data) {
|
|
|
+ return Array.isArray(data)
|
|
|
+ ? data.reduce((acc, item) => ({ ...acc, [item.label]: item.name }), {})
|
|
|
+ : {}
|
|
|
+ },
|
|
|
+ handleImportTableActionEvent(file, options) {
|
|
|
+ IbpsImport.xlsx(file, options).then(({ header, results }) => {
|
|
|
+ const list = []
|
|
|
+ const keys = this.getKeys(this.getColumns())
|
|
|
+ results.forEach((item) => {
|
|
|
+ const obj = {}
|
|
|
+ Object.keys(item).forEach((key) => {
|
|
|
+ if (keys[key]) {
|
|
|
+ obj[keys[key]] = item[key]
|
|
|
+ }
|
|
|
+ })
|
|
|
+ list.push(obj)
|
|
|
+ })
|
|
|
+ const filteredArray = list
|
|
|
+ .map((item) => {
|
|
|
+ if (item.jianCeXiangMu && item.biaoZhun && item.jieLun) {
|
|
|
+ return item
|
|
|
+ }
|
|
|
+ return null
|
|
|
+ })
|
|
|
+ .filter((item) => item !== null)
|
|
|
+ filteredArray.forEach((item) => {
|
|
|
+ list.forEach((el) => {
|
|
|
+ if (el.jianCeXiangMu === item.jianCeXiangMu) {
|
|
|
+ el.biaoZhun = item.biaoZhun
|
|
|
+ el.jieLun = item.jieLun
|
|
|
+ el.xiangMuFuHeLv = item.xiangMuFuHeLv
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ if (el.shiJiChaZhi) {
|
|
|
+ el.shiJiChaZhi = (el.shiJiChaZhi + '').replace('-', '')
|
|
|
+ }
|
|
|
+ if (el.jieGuo) {
|
|
|
+ el.jieGuo = (el.jieGuo + '').replace('-', '')
|
|
|
+ }*/
|
|
|
+ })
|
|
|
+ })
|
|
|
+ this.reagentData = list
|
|
|
+ this.disabled = true
|
|
|
+ this.importTableDialogVisible = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 当前页码改变
|
|
|
+ handleCurrentChange(val) {
|
|
|
+ this.requestPage.pageNo = val
|
|
|
+ },
|
|
|
+ // 页码选择器改变
|
|
|
+ handleSizeChange(val) {
|
|
|
+ this.requestPage.limit = val
|
|
|
+ this.requestPage.pageNo = 1
|
|
|
+ },
|
|
|
+ showAndHide(data) {
|
|
|
+ if (
|
|
|
+ data.includes('平行试验') ||
|
|
|
+ data.includes('留样再测') ||
|
|
|
+ data.includes('比对方案')
|
|
|
+ ) {
|
|
|
+ this.show = true
|
|
|
+ } else {
|
|
|
+ this.show = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 计算结果
|
|
|
+ computedResult() {
|
|
|
+ if (this.disabled) {
|
|
|
+ this.$message.warning('导入数据请勿使用计算功能!')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const hasInvalidData = this.reagentData.some(
|
|
|
+ (item) =>
|
|
|
+ !item.jiuJieGuo ||
|
|
|
+ item.jiuJieGuo <= 0 ||
|
|
|
+ !item.xinJieGuo ||
|
|
|
+ item.xinJieGuo <= 0
|
|
|
+ )
|
|
|
+
|
|
|
+ if (hasInvalidData || this.reagentData.length === 0) {
|
|
|
+ this.$message.warning('新、旧试剂测得结果必须大于0且不能为空!')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const hasPyOrCz = this.reagentData.some(
|
|
|
+ (item) =>
|
|
|
+ (item.jiSuanFangShi === 'Y-X/X(%)' && !item.yunXuPianYi) ||
|
|
|
+ (item.jiSuanFangShi === 'Y-X' && !item.zuiXiaoFanWei)
|
|
|
+ )
|
|
|
+
|
|
|
+ if (hasPyOrCz) {
|
|
|
+ this.$message.warning(
|
|
|
+ `计算方式为 Y-X/X(%) 请填写允许偏倚,计算方式为 Y-X 请填写${
|
|
|
+ this.isHz ? '允许差值' : '限定范围'
|
|
|
+ }`
|
|
|
+ )
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 预处理函数:统一处理百分比数值
|
|
|
+ const normalizePercent = (val) =>
|
|
|
+ Number(String(val).replace('%', '')) || 0
|
|
|
+
|
|
|
+ // 使用 Map 存储统计信息
|
|
|
+ const projectStats = new Map()
|
|
|
+
|
|
|
+ this.reagentData.forEach((item) => {
|
|
|
+ const {
|
|
|
+ jiSuanFangShi,
|
|
|
+ xinJieGuo,
|
|
|
+ jiuJieGuo,
|
|
|
+ zuiXiaoFanWei,
|
|
|
+ jianCeXiangMu
|
|
|
+ } = item
|
|
|
+
|
|
|
+ // 计算差值/偏倚
|
|
|
+ if (jiSuanFangShi === 'Y-X') {
|
|
|
+ //item.shiJiChaZhi = Math.abs((xinJieGuo * 100000 - jiuJieGuo * 100000) / 100000)
|
|
|
+ item.shiJiChaZhi = (xinJieGuo * 100000 - jiuJieGuo * 100000) / 100000
|
|
|
+ item.xiangFu =
|
|
|
+ normalizePercent(item.shiJiChaZhi) <=
|
|
|
+ normalizePercent(zuiXiaoFanWei)
|
|
|
+ ? '相符'
|
|
|
+ : '不相符'
|
|
|
+ item.jieGuo = ''
|
|
|
+ } else {
|
|
|
+ //item.jieGuo = this.deleteAccuracy(Math.abs(xinJieGuo - jiuJieGuo) / jiuJieGuo)
|
|
|
+ item.jieGuo = this.deleteAccuracy((xinJieGuo - jiuJieGuo) / jiuJieGuo)
|
|
|
+ item.xiangFu =
|
|
|
+ normalizePercent(item.jieGuo) <= normalizePercent(item.yunXuPianYi)
|
|
|
+ ? '相符'
|
|
|
+ : '不相符'
|
|
|
+ item.shiJiChaZhi = ''
|
|
|
+ }
|
|
|
+
|
|
|
+ // 统计符合率
|
|
|
+ const stats = projectStats.get(jianCeXiangMu) || { total: 0, yes: 0 }
|
|
|
+ stats.total++
|
|
|
+ if (item.xiangFu === '相符') stats.yes++
|
|
|
+ projectStats.set(jianCeXiangMu, stats)
|
|
|
+ })
|
|
|
+
|
|
|
+ // 填充符合率标准,保留小数点后两位
|
|
|
+ this.reagentData.forEach((item) => {
|
|
|
+ const stats = projectStats.get(item.jianCeXiangMu)
|
|
|
+ item.biaoZhun = this.deleteAccuracy(stats.yes / stats.total)
|
|
|
+ console.log(parseFloat(item.biaoZhun), item.xiangMuFuHeLv)
|
|
|
+ item.jieLun =
|
|
|
+ parseFloat(item.biaoZhun) >=
|
|
|
+ parseFloat(item.xiangMuFuHeLv.replace(/[≥=%]/g, ''))
|
|
|
+ ? '可接受'
|
|
|
+ : '不可接受'
|
|
|
+ })
|
|
|
+ },
|
|
|
+ spanMethod({ row, column, rowIndex, columnIndex }) {
|
|
|
+ if (
|
|
|
+ columnIndex === 1 ||
|
|
|
+ columnIndex === 12 ||
|
|
|
+ columnIndex === 13 ||
|
|
|
+ columnIndex === 14
|
|
|
+ ) {
|
|
|
+ const currentValue = row[column.property]
|
|
|
+ const preRow = this.reagentData[rowIndex - 1]
|
|
|
+ // 上一行这一列的数据
|
|
|
+ const preValue = preRow ? preRow[column.property] : null
|
|
|
+ // 如果当前值和上一行的值相同,则将当前单元格隐藏
|
|
|
+ // 给第0,10,11,12列对数值相同且是同一个'jianCeXiangMu'进行表格合并
|
|
|
+ if (
|
|
|
+ currentValue === preValue &&
|
|
|
+ row['jianCeXiangMu'] === preRow['jianCeXiangMu']
|
|
|
+ ) {
|
|
|
+ return { rowspan: 0, colspan: 0 }
|
|
|
+ } else {
|
|
|
+ let rowspan = 1
|
|
|
+ // 计算应该合并的行数
|
|
|
+ for (let i = rowIndex + 1; i < this.reagentData.length; i++) {
|
|
|
+ const nextRow = this.reagentData[i]
|
|
|
+ const nextValue = nextRow[column.property]
|
|
|
+ if (
|
|
|
+ nextValue === currentValue &&
|
|
|
+ nextRow['jianCeXiangMu'] === row['jianCeXiangMu']
|
|
|
+ ) {
|
|
|
+ rowspan++
|
|
|
+ } else {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return { rowspan, colspan: 1 }
|
|
|
+ }
|
|
|
+ // if (rowIndex % rowspan === 0) {
|
|
|
+ // return {
|
|
|
+ // rowspan,
|
|
|
+ // colspan: 1
|
|
|
+ // }
|
|
|
+ // } else {
|
|
|
+ // return {
|
|
|
+ // rowspan: 0,
|
|
|
+ // colspan: 0
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 去除小数*100精度方法(支持负数)
|
|
|
+ deleteAccuracy(num) {
|
|
|
+ // 处理负数
|
|
|
+ const isNegative = num < 0
|
|
|
+ const absoluteNum = Math.abs(num)
|
|
|
+
|
|
|
+ // 是否带小数点
|
|
|
+ if (absoluteNum.toString().includes('.')) {
|
|
|
+ // 保留小数点后面3位
|
|
|
+ const numArry = absoluteNum.toFixed(3).toString().split('.')
|
|
|
+ let result
|
|
|
+
|
|
|
+ // 整数位是否大于0
|
|
|
+ if (numArry[0] > 0) {
|
|
|
+ result = Number(
|
|
|
+ numArry[0] +
|
|
|
+ numArry[1].substring(0, 2) +
|
|
|
+ '.' +
|
|
|
+ numArry[1].substring(2, 3)
|
|
|
+ ) + '%'
|
|
|
+ } else {
|
|
|
+ // 小数位第一位是否大于0
|
|
|
+ if (numArry[1][0] > 0) {
|
|
|
+ result = Number(
|
|
|
+ numArry[1].substring(0, 2) + '.' + numArry[1].substring(2, 3)
|
|
|
+ ) + '%'
|
|
|
+ } else {
|
|
|
+ // 小数位第二位是否大于0
|
|
|
+ if (numArry[1][1] > 0) {
|
|
|
+ result = Number(
|
|
|
+ numArry[1].substring(1, 2) + '.' + numArry[1].substring(2, 3)
|
|
|
+ ) + '%'
|
|
|
+ } else {
|
|
|
+ result = Number(0 + '.' + numArry[1].substring(2, 3)) + '%'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 恢复负号
|
|
|
+ return isNegative ? '-' + result : result
|
|
|
+ } else {
|
|
|
+ const result = absoluteNum * 100 + '%'
|
|
|
+ return isNegative ? '-' + result : result
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.reagentChange {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ .button {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 0px 0px 0px 15px;
|
|
|
+ background: #f0ffff;
|
|
|
+ .title {
|
|
|
+ color: #999;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: bold;
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+ .el-button {
|
|
|
+ margin: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|