feat:分析
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
// 在此不用配置接口前缀
|
// 在此不用配置接口前缀
|
||||||
const isDev = process.env.NODE_ENV === 'development'
|
const isDev = process.env.NODE_ENV === 'development'
|
||||||
const BaseUrl = isDev ? 'http://192.168.26.116:888/admin-api' : 'http://172.33.199.28:8088/api'
|
const BaseUrl = isDev ? 'http://192.168.26.190:48080/admin-api' : 'http://172.33.199.28:8088/api'
|
||||||
|
|
||||||
// const BaseUrl = isDev ? 'http://localhost:9999' : ''
|
// const BaseUrl = isDev ? 'http://localhost:9999' : ''
|
||||||
const upgradeBaseUrl = 'http://172.33.199.28:8088'
|
const upgradeBaseUrl = 'http://172.33.199.28:8088'
|
||||||
@@ -31,5 +31,5 @@ export function getUpgradeBaseUrl() {
|
|||||||
}
|
}
|
||||||
export function getWebSocketUrl() {
|
export function getWebSocketUrl() {
|
||||||
// return uni.getStorageSync('base_url').replace('/api', '') + '/ws'
|
// return uni.getStorageSync('base_url').replace('/api', '') + '/ws'
|
||||||
return 'ws://192.168.26.178:8330'
|
return 'ws://192.168.26.190:8330'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,14 @@ const getSampleAnalysisByTaskId = businessAssayTaskId => {
|
|||||||
params: { businessAssayTaskId }
|
params: { businessAssayTaskId }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 质控样
|
||||||
|
const batchSampleAndQcAnalysisByTaskId = businessAssayTaskId => {
|
||||||
|
return request({
|
||||||
|
url: '/qms/bus/sample/analysis/batchSampleAndQcAnalysisByTaskId',
|
||||||
|
method: 'GET',
|
||||||
|
params: { businessAssayTaskId }
|
||||||
|
})
|
||||||
|
}
|
||||||
// 获取指派单动态配置项
|
// 获取指派单动态配置项
|
||||||
const getDynamicBaseFormSchema = params => {
|
const getDynamicBaseFormSchema = params => {
|
||||||
return request({
|
return request({
|
||||||
@@ -161,6 +169,17 @@ const saveDetailValue = data => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 批量保存任务
|
||||||
|
const saveBatchSmpleAndQcAnalysis = data => {
|
||||||
|
return request({
|
||||||
|
url: '/qms/bus/sample/analysis/saveBatchSmpleAndQcAnalysis',
|
||||||
|
method: 'POST',
|
||||||
|
data,
|
||||||
|
custom: {
|
||||||
|
showSuccess: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 提交任务明细-停用
|
// 提交任务明细-停用
|
||||||
const submitTaskDetail = params => {
|
const submitTaskDetail = params => {
|
||||||
@@ -256,6 +275,8 @@ export default {
|
|||||||
getAssayTaskList,
|
getAssayTaskList,
|
||||||
getAssayTaskDataList,
|
getAssayTaskDataList,
|
||||||
getSampleAnalysisByTaskId,
|
getSampleAnalysisByTaskId,
|
||||||
|
batchSampleAndQcAnalysisByTaskId,
|
||||||
|
saveBatchSmpleAndQcAnalysis,
|
||||||
getDynamicBaseFormSchema,
|
getDynamicBaseFormSchema,
|
||||||
getAssayTaskDetailListByTaskNo,
|
getAssayTaskDetailListByTaskNo,
|
||||||
getAssayTaskDetailById,
|
getAssayTaskDetailById,
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ math.config({
|
|||||||
number: 'BigNumber',
|
number: 'BigNumber',
|
||||||
precision: 64
|
precision: 64
|
||||||
})
|
})
|
||||||
|
export { math }
|
||||||
/*
|
/*
|
||||||
* 计算分析值*/
|
* 计算当前样品分析值*/
|
||||||
export function calcAnalysisValue(group) {
|
export function calcAnalysisValue(group) {
|
||||||
try {
|
try {
|
||||||
for (const g of group) {
|
for (const g of group) {
|
||||||
@@ -57,6 +58,43 @@ export function calcAnalysisValue(group) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 根据样品和配置列计算分析值
|
||||||
|
export function calcRowAnalysisValue(row, columnObj, dynamicsColumns) {
|
||||||
|
if (!columnObj.paramNo) return
|
||||||
|
for (let i = 0; i < dynamicsColumns.length; i++) {
|
||||||
|
let curItem = dynamicsColumns[i]
|
||||||
|
if (curItem.fieldIndex === columnObj.fieldIndex) continue
|
||||||
|
|
||||||
|
let param = columnObj.fieldIndex.charAt(0) === 'p' ? 'p' + columnObj.paramNo : 'e' + columnObj.paramNo
|
||||||
|
if (curItem.formula && curItem.formula.includes(param)) {
|
||||||
|
let formula = curItem.formula
|
||||||
|
let formulas = formula.split('|')
|
||||||
|
let formulaVal = ''
|
||||||
|
formulas.forEach(f => {
|
||||||
|
if (f.charAt(0) === 'p') {
|
||||||
|
let o = dynamicsColumns.find(i => 'p' + i.paramNo === f)
|
||||||
|
formulaVal += row[o.fieldIndex]?.value ? row[o.fieldIndex].value : 0
|
||||||
|
} else if (f.charAt(0) === 'e') {
|
||||||
|
let o = dynamicsColumns.find(i => 'e' + i.paramNo === f)
|
||||||
|
formulaVal += row[o.fieldIndex]?.value ? row[o.fieldIndex].value : 0
|
||||||
|
} else {
|
||||||
|
formulaVal += f
|
||||||
|
}
|
||||||
|
})
|
||||||
|
let v
|
||||||
|
if (formulaVal.startsWith('Get')) {
|
||||||
|
formulaVal = formulaVal.replace(')', ",'" + row.conBaseSampleId + "')")
|
||||||
|
v = eval(formulaVal)
|
||||||
|
} else {
|
||||||
|
v = math.evaluate(formulaVal).toString()
|
||||||
|
v = isFinite(v) ? v : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
row[curItem.fieldIndex].value = handleRoundFiveNumber(Number(v), row[curItem.fieldIndex].decimalPosition)
|
||||||
|
calcRowAnalysisValue(row, curItem, dynamicsColumns)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
const findFieldInGroup = function (paramNo, group, p) {
|
const findFieldInGroup = function (paramNo, group, p) {
|
||||||
for (const g of group) {
|
for (const g of group) {
|
||||||
for (const f of g.fields) {
|
for (const f of g.fields) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import $router from '@/nx/router'
|
import $router from '@/nx/router'
|
||||||
import $helper from '@/nx/helper'
|
import $helper from '@/nx/helper'
|
||||||
|
import $test from '@/nx/helper/test'
|
||||||
import $store from '@/nx/store'
|
import $store from '@/nx/store'
|
||||||
import $measure from '@/nx/helper/measure'
|
import $measure from '@/nx/helper/measure'
|
||||||
import $print from '@/nx/helper/print'
|
import $print from '@/nx/helper/print'
|
||||||
@@ -21,7 +22,8 @@ const nx = {
|
|||||||
$measure,
|
$measure,
|
||||||
$print,
|
$print,
|
||||||
$dayjs: dayjs,
|
$dayjs: dayjs,
|
||||||
$api
|
$api,
|
||||||
|
$test
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载Nx底层依赖
|
// 加载Nx底层依赖
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
nx.$measure.setRegData(JSON.stringify(regData))
|
nx.$measure.setRegData(JSON.stringify(regData))
|
||||||
|
|
||||||
nx.$measure.open()
|
nx.$measure.open()
|
||||||
|
|
||||||
// 监听 WebSocket 数据
|
// 监听 WebSocket 数据
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<view class="u-tab-item" :class="{ 'u-tab-item-active': active }" @tap.stop="handleClick">
|
<view class="u-tab-item" :class="{ 'u-tab-item-active': active }" @tap.stop="handleClick">
|
||||||
<u-row class="full-width">
|
<u-row class="full-width">
|
||||||
<u-col span="2" class="text-center" style="position: relative">
|
<u-col span="2" class="text-center" style="position: relative">
|
||||||
<u-icon :color="taskStyle(task)" name="tags-fill" size="34"></u-icon>
|
<u-icon :color="taskStyle(task)" name="tags-fill" size="40"></u-icon>
|
||||||
<text class="seq">{{ seq }}</text>
|
<text class="seq">{{ seq }}</text>
|
||||||
</u-col>
|
</u-col>
|
||||||
<u-col span="10">
|
<u-col span="10">
|
||||||
@@ -72,7 +72,7 @@ const taskStyle = task => {
|
|||||||
}
|
}
|
||||||
.seq {
|
.seq {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 9px;
|
top: 12px;
|
||||||
left: 12px;
|
left: 12px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
|
|||||||
@@ -9,28 +9,30 @@
|
|||||||
|
|
||||||
<u-row gutter="8">
|
<u-row gutter="8">
|
||||||
<u-col span="3">
|
<u-col span="3">
|
||||||
<view class="content-title-name">
|
<up-tabs
|
||||||
<text>待化验样品</text>
|
:current="activeAssayTypeIndex"
|
||||||
</view>
|
:list="assayGroups"
|
||||||
|
lineColor="#5ac725"
|
||||||
|
:activeStyle="{
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: '#0055a2'
|
||||||
|
}"
|
||||||
|
:itemStyle="{
|
||||||
|
height: '35px'
|
||||||
|
}"
|
||||||
|
@change="handleAssayTypeChange"
|
||||||
|
></up-tabs>
|
||||||
<u-gap height="5" bg-color="#0055A2"></u-gap>
|
<u-gap height="5" bg-color="#0055A2"></u-gap>
|
||||||
</u-col>
|
</u-col>
|
||||||
<u-col span="6">
|
<u-col span="6">
|
||||||
<view class="content-title-name">
|
<view class="content-title-name">
|
||||||
<view class="current-sample-code">{{ currentSample.sampleCode }}</view>
|
<view class="current-sample-code">{{ currentSampleData.sampleCode }}</view>
|
||||||
<view>数据采集或录入</view>
|
<view>数据采集或录入</view>
|
||||||
</view>
|
</view>
|
||||||
<u-gap height="5" bg-color="#0055A2"></u-gap>
|
<u-gap height="5" bg-color="#0055A2"></u-gap>
|
||||||
</u-col>
|
</u-col>
|
||||||
<u-col span="3">
|
<u-col span="3">
|
||||||
<view class="content-title-name">
|
<u-dropdown style="height: 35px">
|
||||||
<text>样品详情</text>
|
|
||||||
</view>
|
|
||||||
<u-gap height="5" bg-color="#0055A2"></u-gap>
|
|
||||||
</u-col>
|
|
||||||
</u-row>
|
|
||||||
<u-row gutter="8" align="top">
|
|
||||||
<u-col span="3">
|
|
||||||
<u-dropdown>
|
|
||||||
<u-dropdown-item
|
<u-dropdown-item
|
||||||
v-model="curParameterClassify"
|
v-model="curParameterClassify"
|
||||||
:title="curParameterTitle"
|
:title="curParameterTitle"
|
||||||
@@ -39,9 +41,14 @@
|
|||||||
@change="parameterClassifyChange"
|
@change="parameterClassifyChange"
|
||||||
></u-dropdown-item>
|
></u-dropdown-item>
|
||||||
</u-dropdown>
|
</u-dropdown>
|
||||||
|
<u-gap height="5" bg-color="#0055A2"></u-gap>
|
||||||
|
</u-col>
|
||||||
|
</u-row>
|
||||||
|
<u-row gutter="8" align="top">
|
||||||
|
<u-col span="3">
|
||||||
<scroll-view class="content-left-scroll" scroll-with-animation scroll-y :scroll-top="scrollTop">
|
<scroll-view class="content-left-scroll" scroll-with-animation scroll-y :scroll-top="scrollTop">
|
||||||
<view
|
<view
|
||||||
v-for="(sample, index) in leftList"
|
v-for="(sample, index) in sampleDataList"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="u-tab-item"
|
class="u-tab-item"
|
||||||
:class="currentSampleIndex === index ? 'u-tab-item-active' : ''"
|
:class="currentSampleIndex === index ? 'u-tab-item-active' : ''"
|
||||||
@@ -63,10 +70,10 @@
|
|||||||
<view class="field-name" v-html="selectedField.title" />
|
<view class="field-name" v-html="selectedField.title" />
|
||||||
<zzjc-num-keyboard
|
<zzjc-num-keyboard
|
||||||
ref="myKeyboard"
|
ref="myKeyboard"
|
||||||
v-show="selectedField.fillingWay == '1' && selectedField.type != 'select'"
|
v-show="selectedField.fillingWay == 'keyboard' && selectedField.type != 'select'"
|
||||||
:numKeyboardParam="numKeyboardParam"
|
:numKeyboardParam="numKeyboardParam"
|
||||||
></zzjc-num-keyboard>
|
></zzjc-num-keyboard>
|
||||||
<view v-if="selectedField.fillingWay == '2'" class="y-f">
|
<view v-if="selectedField.fillingWay == 'collect'" class="y-f">
|
||||||
<view class="auncel" @click="selectAuncel">
|
<view class="auncel" @click="selectAuncel">
|
||||||
<view class="auncel-title"> {{ currentAuncel.code }}</view>
|
<view class="auncel-title"> {{ currentAuncel.code }}</view>
|
||||||
<view class="auncel-weight">
|
<view class="auncel-weight">
|
||||||
@@ -103,11 +110,10 @@
|
|||||||
<view>
|
<view>
|
||||||
<scroll-view class="content-right-scroll" scroll-y scroll-with-animation>
|
<scroll-view class="content-right-scroll" scroll-y scroll-with-animation>
|
||||||
<view>
|
<view>
|
||||||
<u-form :model="curSample" ref="uForm" label-width="140">
|
<!-- <template v-for="(fields, groupIndex) in fieldGroup" :key="'group_' + groupIndex"> -->
|
||||||
<template v-for="(fields, groupIndex) in fieldGroup" :key="'group_' + groupIndex">
|
<!-- <view> -->
|
||||||
<view>
|
|
||||||
<!-- 组名 -->
|
<!-- 组名 -->
|
||||||
<view class="my-collapse" @click="fields.open = !fields.open">
|
<!-- <view class="my-collapse" @click="fields.open = !fields.open">
|
||||||
<text class="title">{{ fields.title }}</text>
|
<text class="title">{{ fields.title }}</text>
|
||||||
<u-icon :name="fields.open ? 'arrow-up' : 'arrow-down'"></u-icon>
|
<u-icon :name="fields.open ? 'arrow-up' : 'arrow-down'"></u-icon>
|
||||||
</view>
|
</view>
|
||||||
@@ -115,7 +121,9 @@
|
|||||||
class="content"
|
class="content"
|
||||||
:id="'elId' + groupIndex"
|
:id="'elId' + groupIndex"
|
||||||
:style="{ height: fields.open ? collaHeights[groupIndex] + 'px' : '0' }"
|
:style="{ height: fields.open ? collaHeights[groupIndex] + 'px' : '0' }"
|
||||||
>
|
> -->
|
||||||
|
<up-collapse ref="collapseRef" :value="activeCollapses">
|
||||||
|
<up-collapse-item v-for="(fields, groupIndex) in fieldGroup" :title="fields.title">
|
||||||
<view
|
<view
|
||||||
class="form-item-my"
|
class="form-item-my"
|
||||||
v-for="(field, fieldIndex) in fields.fields"
|
v-for="(field, fieldIndex) in fields.fields"
|
||||||
@@ -140,7 +148,7 @@
|
|||||||
<u-input
|
<u-input
|
||||||
border="bottom"
|
border="bottom"
|
||||||
style="width: 120px"
|
style="width: 120px"
|
||||||
v-if="field.fillingWay == 4"
|
v-if="field.fillingWay == 'input'"
|
||||||
v-model="field.value"
|
v-model="field.value"
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
/>
|
/>
|
||||||
@@ -159,22 +167,21 @@
|
|||||||
@confirm="event => dicPickerConfirm(event, field)"
|
@confirm="event => dicPickerConfirm(event, field)"
|
||||||
/> -->
|
/> -->
|
||||||
<!--普通输入框 使用文本显示-->
|
<!--普通输入框 使用文本显示-->
|
||||||
<view class="content-my-text" v-if="field.dataType != 'select' && field.fillingWay != 4">
|
<view class="content-my-text" v-if="field.dataType != 'select' && field.fillingWay != 'input'">
|
||||||
<text v-if="!field.value" class="content-my-text-placeholder">{{
|
<text v-if="!field.value" class="content-my-text-placeholder">{{
|
||||||
!field.fillingWay || field.fillingWay == 3 ? '计算值' : '请输入'
|
!field.fillingWay || field.fillingWay == 'calculate' ? '计算值' : '请输入'
|
||||||
|
}}</text>
|
||||||
|
<text v-else :class="['content-my-text-value', { 'field-high-light': field.highlight == 1 }]">{{
|
||||||
|
field.value
|
||||||
}}</text>
|
}}</text>
|
||||||
<text
|
|
||||||
v-else
|
|
||||||
:class="['content-my-text-value', { 'field-high-light': field.highlight == 1 }]"
|
|
||||||
>{{ field.value }}</text
|
|
||||||
>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</up-collapse-item>
|
||||||
</view>
|
</up-collapse>
|
||||||
</template>
|
<!-- </view>
|
||||||
</u-form>
|
</view> -->
|
||||||
|
<!-- </template> -->
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<u-button class="btn-operation" type="success" @click="saveDetail()">保存样品数据</u-button>
|
<u-button class="btn-operation" type="success" @click="saveDetail()">保存样品数据</u-button>
|
||||||
@@ -192,10 +199,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, computed, nextTick, getCurrentInstance } from 'vue'
|
import { ref, reactive, computed, nextTick, watch, getCurrentInstance } from 'vue'
|
||||||
import { onLoad, onBackPress, onShow, onHide, onUnload } from '@dcloudio/uni-app'
|
import { onLoad, onBackPress, onShow, onHide, onUnload } from '@dcloudio/uni-app'
|
||||||
import request from '@/nx/request'
|
import request from '@/nx/request'
|
||||||
import { calcAnalysisValue } from '@/nx/helper/calcAnalysisValue'
|
import { calcAnalysisValue, handleRoundFiveNumber, calcRowAnalysisValue, math } from '@/nx/helper/calcAnalysisValue'
|
||||||
import { number } from 'mathjs'
|
import { number } from 'mathjs'
|
||||||
import AuncelSelectPopup from '@/components/sample/auncel-select-popup.vue'
|
import AuncelSelectPopup from '@/components/sample/auncel-select-popup.vue'
|
||||||
import { getTenantId } from '@/defaultBaseUrl'
|
import { getTenantId } from '@/defaultBaseUrl'
|
||||||
@@ -212,9 +219,8 @@ const scrollTop = ref(0) //tab标题的滚动条位置
|
|||||||
const menuHeight = ref(0) // 左边菜单的高度
|
const menuHeight = ref(0) // 左边菜单的高度
|
||||||
const menuItemHeight = ref(0) // 左边菜单item的高度
|
const menuItemHeight = ref(0) // 左边菜单item的高度
|
||||||
const weightDataIsToZero = ref(false) //重量数据是否归零
|
const weightDataIsToZero = ref(false) //重量数据是否归零
|
||||||
const currentSample = ref({}) //当前样品
|
|
||||||
const currentSampleIndex = ref(0) // 预设当前项的值
|
const currentSampleIndex = ref(0) // 预设当前项的值
|
||||||
let sampleDataList = []
|
let sampleDataList = ref([])
|
||||||
const title = ref('')
|
const title = ref('')
|
||||||
const numKeyboardParam = reactive({
|
const numKeyboardParam = reactive({
|
||||||
decimal: '-1' //数字键盘小数位数,-1为不限制
|
decimal: '-1' //数字键盘小数位数,-1为不限制
|
||||||
@@ -230,7 +236,6 @@ const currentAuncel = ref({
|
|||||||
})
|
})
|
||||||
let selectedField = ref({})
|
let selectedField = ref({})
|
||||||
const groupFieldIndex = ref('') //分组的索引
|
const groupFieldIndex = ref('') //分组的索引
|
||||||
const leftList = ref([])
|
|
||||||
const curSample = ref({})
|
const curSample = ref({})
|
||||||
const curParameterTitle = ref('选择字段分类')
|
const curParameterTitle = ref('选择字段分类')
|
||||||
const curParameterKey = ref('')
|
const curParameterKey = ref('')
|
||||||
@@ -249,7 +254,7 @@ const auncelSelector = ref(null)
|
|||||||
// 计算属性
|
// 计算属性
|
||||||
const confirmWeightDisabled = computed(() => {
|
const confirmWeightDisabled = computed(() => {
|
||||||
if (
|
if (
|
||||||
currentSample.value.sampleCode &&
|
currentSampleData.value.sampleCode &&
|
||||||
currentAuncel.value.weightStable === 1 &&
|
currentAuncel.value.weightStable === 1 &&
|
||||||
Number(currentAuncel.value.weightData) > 0
|
Number(currentAuncel.value.weightData) > 0
|
||||||
) {
|
) {
|
||||||
@@ -257,12 +262,12 @@ const confirmWeightDisabled = computed(() => {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
// 当前样品数据索引
|
// 当前样品数据
|
||||||
const currentSampleDataIndex = computed(() => {
|
const currentSampleData = computed(() => {
|
||||||
if (sampleDataList.length > 0) {
|
if (sampleDataList.value.length > 0) {
|
||||||
return sampleDataList.findIndex(item => item.businessAssayTaskDataId === currentSample.value.id)
|
return sampleDataList.value[currentSampleIndex.value]
|
||||||
}
|
}
|
||||||
return -1
|
return {}
|
||||||
})
|
})
|
||||||
// 当前操作字段索引
|
// 当前操作字段索引
|
||||||
const currentFieldKey = computed(() => {
|
const currentFieldKey = computed(() => {
|
||||||
@@ -316,15 +321,17 @@ const parameterClassifyChange = (v, a) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fieldClick = (field, key) => {
|
const fieldClick = (field, key) => {
|
||||||
myKeyboard.value.clearNum()
|
if (field.fillingWay == 'input' || !field.fillingWay || field.fillingWay == 'calculate') return
|
||||||
if (field.fillingWay == 4 || !field.fillingWay || field.fillingWay == 3) return
|
|
||||||
selectedField.value = field
|
selectedField.value = field
|
||||||
groupFieldIndex.value = key
|
groupFieldIndex.value = key
|
||||||
|
if (myKeyboard.value) {
|
||||||
|
myKeyboard.value.clearNum()
|
||||||
|
}
|
||||||
//判断小数位数
|
//判断小数位数
|
||||||
let decimalPosition = field.decimalPosition
|
let decimalPosition = field.decimalPosition
|
||||||
if (decimalPosition == null || decimalPosition < -1) decimalPosition = -1
|
if (decimalPosition == null || decimalPosition < -1) decimalPosition = -1
|
||||||
numKeyboardParam.decimal = decimalPosition
|
numKeyboardParam.decimal = decimalPosition
|
||||||
if (field.fillingWay == 2) {
|
if (field.fillingWay == 'keyboard') {
|
||||||
listenDeviceData()
|
listenDeviceData()
|
||||||
} else {
|
} else {
|
||||||
closeDeviceListener()
|
closeDeviceListener()
|
||||||
@@ -350,7 +357,7 @@ const autoNextField = () => {
|
|||||||
|
|
||||||
//自动切换到下一个样品
|
//自动切换到下一个样品
|
||||||
const autoNextSample = () => {
|
const autoNextSample = () => {
|
||||||
if (leftList.value.length <= currentSampleIndex.value + 1) return
|
if (sampleDataList.value.length <= currentSampleIndex.value + 1) return
|
||||||
const index = currentSampleIndex.value + 1
|
const index = currentSampleIndex.value + 1
|
||||||
groupFieldIndex.value = ''
|
groupFieldIndex.value = ''
|
||||||
selectedField.value = {}
|
selectedField.value = {}
|
||||||
@@ -376,7 +383,6 @@ const switchSample = async (index, autoFlag) => {
|
|||||||
// groupFieldIndex.value = groupFieldIndex.value.split('-')[0] + '-'
|
// groupFieldIndex.value = groupFieldIndex.value.split('-')[0] + '-'
|
||||||
// }
|
// }
|
||||||
uni.showLoading({ title: '加载中...' })
|
uni.showLoading({ title: '加载中...' })
|
||||||
currentSample.value = leftList.value[index]
|
|
||||||
setValueToField()
|
setValueToField()
|
||||||
autoGenerateCupNum()
|
autoGenerateCupNum()
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -413,7 +419,7 @@ const getElRect = (elClass, maxRetry = 50) => {
|
|||||||
|
|
||||||
//读取样品明细字段
|
//读取样品明细字段
|
||||||
const getDetailFieldsAndStatus = autoSelectNextField => {
|
const getDetailFieldsAndStatus = autoSelectNextField => {
|
||||||
const taskDetailId = currentSample.value.id
|
const taskDetailId = currentSampleData.value.id
|
||||||
//读取回收率配置
|
//读取回收率配置
|
||||||
loadConRecoveryList()
|
loadConRecoveryList()
|
||||||
optionParameterClassify.value = arr //字段分类
|
optionParameterClassify.value = arr //字段分类
|
||||||
@@ -619,29 +625,96 @@ const saveAuncelData = () => {
|
|||||||
autoNextField()
|
autoNextField()
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
|
const dynamicFormData = {}
|
||||||
const saveDetail = async () => {
|
const saveDetail = async () => {
|
||||||
//检查杯号
|
//检查杯号
|
||||||
if (!checkBh()) return
|
if (!checkBh()) return
|
||||||
let params = {
|
|
||||||
businessAssayTaskId: taskId.value,
|
|
||||||
datas: sampleDataList
|
|
||||||
}
|
|
||||||
setValueToSample()
|
setValueToSample()
|
||||||
await nx.$api.assayTask.saveDetailValue(params)
|
let params = {
|
||||||
|
businessAssayTaskId: taskId.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是空白样和标样就需要根据配置信息来计算质控样、分析样
|
||||||
|
if (activeAssayTypeKey.value === 'kby' || activeAssayTypeKey.value === 'by') {
|
||||||
|
// 处理其他页签的输入变化
|
||||||
|
const configInfomation = currentAssayType.value.configQCSampleMethodInfo
|
||||||
|
const row = sampleDataList.value[currentSampleIndex.value]
|
||||||
|
configInfomation.forEach(item => {
|
||||||
|
const sourceKey = item.source
|
||||||
|
const sourceValue = row[sourceKey]
|
||||||
|
if (sourceValue !== undefined) {
|
||||||
|
if (item.calcMethod === 'calculateAverageValue') {
|
||||||
|
item.value = calcAverageValue(sourceKey, currentAssayType.value.tableData)
|
||||||
|
} else {
|
||||||
|
item.value = handleRoundFiveNumber(row[sourceKey].value, row.decimalPosition)
|
||||||
|
}
|
||||||
|
// 如果处理后的值不为空,重新赋值该字段到其他样品类型下的样品上,并触发每一个样品的计算
|
||||||
|
if (item.value !== null) {
|
||||||
|
dynamicFormData[item.target] = item.value
|
||||||
|
updateTableDataByConfigFields()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
params.formValue = JSON.stringify(dynamicFormData)
|
||||||
|
params.assayTaskAnalysisDataList = assayGroups.value.map(item => ({
|
||||||
|
datas: item.tableData,
|
||||||
|
analysisType: item.value
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
const datas = sampleDataList.value[currentSampleIndex.value]
|
||||||
|
params.assayTaskAnalysisDataList = [{ datas, analysisType: activeAssayTypeKey.value }]
|
||||||
|
}
|
||||||
|
|
||||||
|
await nx.$api.assayTask.saveBatchSmpleAndQcAnalysis(params)
|
||||||
|
getSampleAnalysisByTaskId()
|
||||||
autoNextSample()
|
autoNextSample()
|
||||||
}
|
}
|
||||||
|
// 计算表格列平均值
|
||||||
|
function calcAverageValue(fieldIndex, tableData) {
|
||||||
|
const rows = tableData.map(row => row[fieldIndex])
|
||||||
|
const decimalPosition = rows[0].decimalPosition
|
||||||
|
const values = rows.map(row => Number(row.value))
|
||||||
|
if (values.some(item => item == null)) return null
|
||||||
|
return handleRoundFiveNumber(math.mean(values), decimalPosition)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表格数据更新后重新计算
|
||||||
|
function updateTableDataByConfigFields() {
|
||||||
|
let needCalcTabs = []
|
||||||
|
needCalcTabs = assayGroups.value.filter(t => t.value !== 'by' && t.value !== 'kby')
|
||||||
|
if (needCalcTabs.length === 0) return
|
||||||
|
for (const key in dynamicFormData) {
|
||||||
|
for (const tab of needCalcTabs) {
|
||||||
|
const columnObj = tab.columns.find(c => {
|
||||||
|
if (c.formula) {
|
||||||
|
let FromKey = c.formula.split(':')
|
||||||
|
return FromKey[1] === key
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
if (!columnObj) continue
|
||||||
|
tab.tableData.forEach(row => {
|
||||||
|
// 赋值配置列参与计算
|
||||||
|
row[columnObj.fieldIndex].value = dynamicFormData[key]
|
||||||
|
calcRowAnalysisValue(row, columnObj, tab.columns)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 把字段值保存回样品数据中
|
// 把字段值保存回样品数据中
|
||||||
function setValueToSample() {
|
function setValueToSample() {
|
||||||
let fields = fieldGroup.value.flatMap(item => item.fields)
|
let fields = fieldGroup.value.flatMap(item => item.fields)
|
||||||
fields.forEach(item => {
|
fields.forEach(item => {
|
||||||
if (sampleDataList[currentSampleDataIndex.value].hasOwnProperty(item.fieldIndex)) {
|
if (
|
||||||
sampleDataList[currentSampleDataIndex.value][item.fieldIndex].value = item.value
|
sampleDataList.value[currentSampleIndex.value].hasOwnProperty(item.fieldIndex) &&
|
||||||
|
nx.$test.object(sampleDataList.value[currentSampleIndex.value][item.fieldIndex])
|
||||||
|
) {
|
||||||
|
sampleDataList.value[currentSampleIndex.value][item.fieldIndex].value = item.value
|
||||||
}
|
}
|
||||||
// 初始化的时候保存杯号到样品中后续自动生成杯号用
|
// 初始化的时候保存杯号到样品中后续自动生成杯号用
|
||||||
if (item.title === cupNumKey && currentSampleIndex.value == 0) {
|
if (item.title === cupNumKey && currentSampleIndex.value == 0) {
|
||||||
leftList.value[currentSampleIndex.value].cupNum = item.value
|
sampleDataList.value[currentSampleIndex.value].cupNum = item.value
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -676,14 +749,14 @@ const autoGenerateCupNum = () => {
|
|||||||
//第一杯
|
//第一杯
|
||||||
if (current === 0) return
|
if (current === 0) return
|
||||||
//取上一个样品的杯号
|
//取上一个样品的杯号
|
||||||
const sample = leftList.value[current - 1]
|
const sample = sampleDataList.value[current - 1]
|
||||||
cupNum = sample.cupNum
|
cupNum = sample.cupNum
|
||||||
//杯号赋值到当前样品
|
//杯号赋值到当前样品
|
||||||
putCupNum(Number(cupNum) + 1, current, Number(cupNum))
|
putCupNum(Number(cupNum) + 1, current, Number(cupNum))
|
||||||
}
|
}
|
||||||
|
|
||||||
const putCupNum = (cupNum, sampleIndex, lastCupNum) => {
|
const putCupNum = (cupNum, sampleIndex, lastCupNum) => {
|
||||||
leftList.value[sampleIndex].cupNum = cupNum
|
sampleDataList.value[sampleIndex].cupNum = cupNum
|
||||||
for (const fields of fieldGroup.value) {
|
for (const fields of fieldGroup.value) {
|
||||||
if (typeof fields === 'undefined') continue
|
if (typeof fields === 'undefined') continue
|
||||||
//杯号
|
//杯号
|
||||||
@@ -727,7 +800,7 @@ const putCupNum = (cupNum, sampleIndex, lastCupNum) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const loadConRecoveryList = () => {
|
const loadConRecoveryList = () => {
|
||||||
const conBaseSampleId = currentSample.value.conBaseSampleId
|
const conBaseSampleId = currentSampleData.value.conBaseSampleId
|
||||||
const rParam = {
|
const rParam = {
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: -1,
|
pageSize: -1,
|
||||||
@@ -754,29 +827,60 @@ const loadConRecoveryList = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAssayTaskSampleList = businessAssayTaskId => {
|
// 分析样品组
|
||||||
leftList.value = []
|
let assayGroups = ref([])
|
||||||
nx.$api.assayTask
|
const activeAssayTypeKey = ref('')
|
||||||
.getAssayTaskDataList({ businessAssayTaskId })
|
const activeAssayTypeIndex = ref(0)
|
||||||
.then(res => {
|
//元素结果范围
|
||||||
leftList.value = res
|
let conRangeElementAnalysisList = []
|
||||||
currentSampleIndex.value = 0
|
const currentAssayType = computed(() => {
|
||||||
currentSample.value = leftList.value[0]
|
return assayGroups.value.find(item => item.value === activeAssayTypeKey.value)
|
||||||
})
|
})
|
||||||
.catch(err => {
|
watch(
|
||||||
console.error(err)
|
() => currentAssayType.value,
|
||||||
})
|
() => {
|
||||||
}
|
sampleDataList.value = currentAssayType.value.tableData
|
||||||
|
fieldGroup.value = [{ open: true, fields: currentAssayType.value.columns, title: '样品分析' }]
|
||||||
async function getSampleAnalysisByTaskId(businessAssayTaskId) {
|
|
||||||
const data = await nx.$api.assayTask.getSampleAnalysisByTaskId(businessAssayTaskId)
|
|
||||||
sampleDataList = data.datas
|
|
||||||
let columns = data.columns.filter(item => item.paramNo)
|
|
||||||
fieldGroup.value = [{ open: true, fields: columns, title: '样品分析' }]
|
|
||||||
setValueToField()
|
setValueToField()
|
||||||
title.value = '样品分析-任务指派单:' + data.businessAssayTasNo
|
// getDomHeight()
|
||||||
getDomHeight()
|
activeCollapses.value = fieldGroup.value.map((_, index) => index)
|
||||||
autoNextField()
|
}
|
||||||
|
)
|
||||||
|
const collapseRef = ref()
|
||||||
|
const activeCollapses = ref([])
|
||||||
|
function handleAssayTypeChange({ index, value }) {
|
||||||
|
activeAssayTypeKey.value = value
|
||||||
|
activeAssayTypeIndex.value = index
|
||||||
|
currentSampleIndex.value = 0
|
||||||
|
groupFieldIndex.value = ''
|
||||||
|
collapseRef.value.init()
|
||||||
|
}
|
||||||
|
// 获取任务指派单数据
|
||||||
|
async function getSampleAnalysisByTaskId() {
|
||||||
|
const { assayTaskAnalysisDataList, configAssayMethodProjectRangeList, businessAssayTasNo } =
|
||||||
|
await nx.$api.assayTask.batchSampleAndQcAnalysisByTaskId(taskId.value)
|
||||||
|
title.value = '样品分析-任务指派单:' + businessAssayTasNo
|
||||||
|
// 处理分析数据
|
||||||
|
assayGroups.value = assayTaskAnalysisDataList.map(group => {
|
||||||
|
// 必须深拷贝 datas!防止多个表格共享引用
|
||||||
|
const tableData = JSON.parse(JSON.stringify(group.datas || []))
|
||||||
|
const columns = group.columns || []
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: group.analysisType,
|
||||||
|
name: group.analysisName,
|
||||||
|
columns,
|
||||||
|
tableData,
|
||||||
|
configQCSampleMethodInfo: group.configQCSampleMethod?.configInfomation
|
||||||
|
? JSON.parse(group.configQCSampleMethod['configInfomation'])['set']
|
||||||
|
: []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 默认激活第一个 类型
|
||||||
|
if (!activeAssayTypeKey.value) {
|
||||||
|
activeAssayTypeKey.value = assayGroups.value.length > 0 ? assayGroups.value[0].value : ''
|
||||||
|
}
|
||||||
|
conRangeElementAnalysisList = configAssayMethodProjectRangeList || []
|
||||||
}
|
}
|
||||||
// 设置字段值
|
// 设置字段值
|
||||||
function setValueToField() {
|
function setValueToField() {
|
||||||
@@ -788,7 +892,7 @@ function setValueToField() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
function getFieldValue(field) {
|
function getFieldValue(field) {
|
||||||
const fieldValue = sampleDataList[currentSampleDataIndex.value][field.fieldIndex].value
|
const fieldValue = sampleDataList.value[currentSampleIndex.value][field.fieldIndex]?.value
|
||||||
if (fieldValue) {
|
if (fieldValue) {
|
||||||
return fieldValue
|
return fieldValue
|
||||||
} else {
|
} else {
|
||||||
@@ -1008,8 +1112,8 @@ onLoad(param => {
|
|||||||
lockOrientation('landscape')
|
lockOrientation('landscape')
|
||||||
if (param.currentTaskId) {
|
if (param.currentTaskId) {
|
||||||
taskId.value = param.currentTaskId
|
taskId.value = param.currentTaskId
|
||||||
getAssayTaskSampleList(taskId.value)
|
// getAssayTaskSampleList(taskId.value)
|
||||||
getSampleAnalysisByTaskId(taskId.value)
|
getSampleAnalysisByTaskId()
|
||||||
}
|
}
|
||||||
loadFieldApiData(fieldGroup.value)
|
loadFieldApiData(fieldGroup.value)
|
||||||
listenNumKeyboard()
|
listenNumKeyboard()
|
||||||
@@ -1112,7 +1216,7 @@ onBackPress(() => {
|
|||||||
color: #c0c4cc;
|
color: #c0c4cc;
|
||||||
}
|
}
|
||||||
.content-left-scroll {
|
.content-left-scroll {
|
||||||
height: 60vh;
|
height: 68vh;
|
||||||
}
|
}
|
||||||
.content-right-scroll {
|
.content-right-scroll {
|
||||||
height: 68vh;
|
height: 68vh;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
v-model="field.value"
|
v-model="field.value"
|
||||||
clearable
|
clearable
|
||||||
:placeholder="field.placeholder"
|
:placeholder="field.placeholder"
|
||||||
:disabled="field.disabled || field.fillingWay == 3"
|
:disabled="field.disabled || field.fillingWay == 'calculate'"
|
||||||
/>
|
/>
|
||||||
<!--数字,限制小数位数-->
|
<!--数字,限制小数位数-->
|
||||||
<u-input
|
<u-input
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
@blur="event => checkDecimal(event, field)"
|
@blur="event => checkDecimal(event, field)"
|
||||||
v-model="field.value"
|
v-model="field.value"
|
||||||
:placeholder="field.placeholder"
|
:placeholder="field.placeholder"
|
||||||
:disabled="field.disabled || field.fillingWay == 3"
|
:disabled="field.disabled || field.fillingWay == 'calculate'"
|
||||||
/>
|
/>
|
||||||
<!--select-->
|
<!--select-->
|
||||||
<view v-if="field.type == 'select'" class="x-bc select-my" @click="handleFieldClick(field)">
|
<view v-if="field.type == 'select'" class="x-bc select-my" @click="handleFieldClick(field)">
|
||||||
@@ -150,12 +150,6 @@ function loadTaskDetail() {
|
|||||||
|
|
||||||
// 点击字段(打开选择器)
|
// 点击字段(打开选择器)
|
||||||
function handleFieldClick(field) {
|
function handleFieldClick(field) {
|
||||||
if (field.type == 'date') {
|
|
||||||
field.showPicker = true
|
|
||||||
if (field.fillingWay == '1') {
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
field.showPicker = true
|
field.showPicker = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<block v-for="(sample, index) in sampleList" :key="index">
|
<block v-for="(sample, index) in sampleList" :key="index">
|
||||||
<view v-if="currentTask.reviewCount === sample.reviewCount" class="p5 fs16">
|
<view v-if="currentTask.reviewCount === sample.reviewCount" class="p5 fs16">
|
||||||
<u-row>
|
<u-row>
|
||||||
<u-col span="3" class="text-center">
|
<u-col span="2" class="text-center">
|
||||||
<u-row>
|
<u-row>
|
||||||
<u-col span="6" class="text-center">
|
<u-col span="6" class="text-center">
|
||||||
<!-- v-if="
|
<!-- v-if="
|
||||||
@@ -49,7 +49,9 @@
|
|||||||
</u-col>
|
</u-col>
|
||||||
</u-row>
|
</u-row>
|
||||||
</u-col>
|
</u-col>
|
||||||
<u-col span="9">
|
<u-col span="10" class="flex">
|
||||||
|
<u-row>
|
||||||
|
<u-col span="6">
|
||||||
<view class="sample_desc">
|
<view class="sample_desc">
|
||||||
<view>
|
<view>
|
||||||
<view
|
<view
|
||||||
@@ -61,18 +63,18 @@
|
|||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- <view class="sample_desc_warn" v-if="sample.sampleProcessNo !== currentNode">
|
|
||||||
当前节点:{{ getProcessNameShow(sample.sampleProcessNo) }}
|
|
||||||
</view>
|
</view>
|
||||||
<view class="sample_desc_warn" v-if="sample.rollbackStatus === 'revoke'"> 样品退回被驳回 </view>
|
</u-col>
|
||||||
<view class="sample_desc_warn" v-if="sample.rollbackStatus === 'running'"> 样品退回审批中 </view>
|
<u-col span="6">
|
||||||
<view class="sample_desc_warn" v-if="sample.rollbackStatus === 'finished'">
|
<view>
|
||||||
样品已退回,请联系管理员处理
|
<text class="pl10">
|
||||||
</view> -->
|
{{ sample.assayProject }}
|
||||||
|
</text>
|
||||||
</view>
|
</view>
|
||||||
</u-col>
|
</u-col>
|
||||||
</u-row>
|
</u-row>
|
||||||
|
</u-col>
|
||||||
|
</u-row>
|
||||||
<u-line class="p5" color="#bbb" />
|
<u-line class="p5" color="#bbb" />
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
@@ -136,7 +138,7 @@ const customBack = () => {
|
|||||||
uni.reLaunch({ url: '/pages/analysis/index/index' })
|
uni.reLaunch({ url: '/pages/analysis/index/index' })
|
||||||
}
|
}
|
||||||
const showRollbackModal = () => {
|
const showRollbackModal = () => {
|
||||||
if (checkedSampleCodes.length === 0) {
|
if (checkedSampleCodes.value.length === 0) {
|
||||||
uni.showToast({ title: '请选择要退回的样品!', icon: 'none' })
|
uni.showToast({ title: '请选择要退回的样品!', icon: 'none' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user