@@ -9,28 +9,30 @@
< u-row gutter = "8" >
< u-col span = "3" >
< view class = "content-title-name" >
< text > 待化验样品 < / text >
< / view >
< up-tabs
:current = "activeAssayTypeIndex"
: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-col >
< u-col span = "6" >
< view class = "content-title-name" >
< view class = "current-sample-code" > { { currentSample . sampleCode } } < / view >
< view class = "current-sample-code" > { { currentSampleData . sampleCode } } < / view >
< view > 数据采集或录入 < / view >
< / view >
< u-gap height = "5" bg -color = " # 0055A2 " > < / u-gap >
< / u-col >
< u-col span = "3" >
< view class = "content-title-name ">
< 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 style = "height: 35px ">
< u-dropdown-item
v-model = "curParameterClassify"
:title = "curParameterTitle"
@@ -39,9 +41,14 @@
@change ="parameterClassifyChange"
> < / u-dropdown-item >
< / 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" >
< view
v-for = "(sample, index) in left List"
v-for = "(sample, index) in sampleData List"
:key = "index"
class = "u-tab-item"
: class = "currentSampleIndex === index ? 'u-tab-item-active' : ''"
@@ -63,10 +70,10 @@
< view class = "field-name" v-html = "selectedField.title" / >
< zzjc-num-keyboard
ref = "myKeyboard"
v-show = "selectedField.fillingWay == '1 ' && selectedField.type != 'select'"
v-show = "selectedField.fillingWay == 'keyboard ' && selectedField.type != 'select'"
:numKeyboardParam = "numKeyboardParam"
> < / 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-title" > { { currentAuncel . code } } < / view >
< view class = "auncel-weight" >
@@ -103,11 +110,10 @@
< view >
< scroll-view class = "content-right-scroll" scroll -y scroll -with -animation >
< view >
< u-form :model = "curSample" ref = "uForm" label -width = " 140 " >
< template v-for = "(fields, groupIndex) in fieldGroup" :key="'group_' + groupIndex" >
< view >
<!-- 组名 -- >
< view class = "my-collapse" @click ="fields.open = !fields.open" >
<!-- < template v-for = "(fields, groupIndex) in fieldGroup" :key="'group_' + groupIndex" > - - >
<!-- < view > -- >
<!-- 组名 -- >
<!-- < view class = "my-collapse" @click ="fields.open = !fields.open" >
< text class = "title" > { { fields . title } } < / text >
< u-icon : name = "fields.open ? 'arrow-up' : 'arrow-down'" > < / u-icon >
< / view >
@@ -115,37 +121,39 @@
class = "content"
: id = "'elId' + groupIndex"
: style = "{ height: fields.open ? collaHeights[groupIndex] + 'px' : '0' }"
>
< view
class = "form-item-my"
v-for = "(field, fieldIndex) in fields.fields"
@click ="fieldClick(field, groupIndex + '-' + fieldIndex) "
: key = "groupIndex + '-' + fieldIndex "
v-show = "field.hidden != 1 "
: class = "{
'selected-field': groupFieldIndex === groupIndex + '-' + fieldIndex,
'disabled-field': !field.isEdit
}"
>
< view
: class = "['label-my', { 'label-high-light': field.highlight == 1 }]"
v-html = "field.title"
> < / view >
< view class = "content-my" >
<!--
> -- >
< up-collapse ref = "collapseRef" :value = "activeCollapses" >
< up-collapse-item v-for = "(fields, groupIndex) in fieldGroup" :title="fields.title" >
< view
class = "form-item-my "
v-for = "(field, fieldIndex) in fields.fields "
@click = "fieldClick(field, groupIndex + '-' + fieldIndex) "
: key = "groupIndex + '-' + fieldIndex"
v-show = "field.hidden != 1"
: class = "{
'selected-field': groupFieldIndex === groupIndex + '-' + fieldIndex,
'disabled-field': !field.isEdit
}"
>
< view
: class = "['label-my', { 'label-high-light': field.highlight == 1 }]"
v-html = "field.title"
> < / view >
< view class = "content-my" >
<!--
如果是select , 渲染2个组件 : 1 个input 、 1 个picker .
field . valueText用于显示picker选中的文本
1 , 键盘输入 , 2 、 天平 , 3 、 自动计算 , 4 、 文本输入
-- >
< u-input
border = "bottom"
style = "width: 120px"
v-if = "field.fillingWay == 4 "
v-model = "field.value"
placeholder = "请输入"
/ >
< u-input
border = "bottom"
style = "width: 120px"
v-if = "field.fillingWay == 'input' "
v-model = "field.value"
placeholder = "请输入"
/ >
<!-- < view v-if = "field.type === 'select'" class="x-bc select-my" @click="field.showPicker = true" >
<!-- < view v-if = "field.type === 'select'" class="x-bc select-my" @click="field.showPicker = true" >
< text v-if = "field.valueText" > {{ field.valueText }} < / text >
< text v-else > 请选择 < / text >
< u -icon name = "arrow-down" size = "20" > < / u-icon >
@@ -158,23 +166,22 @@
@cancel ="field.showPicker = false"
@confirm ="event => dicPickerConfirm(event, field)"
/ > -- >
<!-- 普通输入框 使用文本显示 -- >
< view class = "content-my-text" v-if = "field.dataType != 'select' && field.fillingWay != 4 " >
< text v-if = "!field.value" class="content-my-text-placeholder" > {{
! field.fillingWay | | field.fillingWay = = 3 ? ' 计算值 ' : ' 请输入 '
}} < / text >
< text
v-els e
: class = "['content-my-text-value', { 'field-high-light': field.highlight == 1 }]"
> { { field . value } } < / t e x t
>
< / view >
< / view >
<!-- 普通输入框 使用文本显示 -- >
< view class = "content-my-text" v-if = "field.dataType != 'select' && field.fillingWay != 'input' " >
< text v-if = "!field.value" class="content-my-text-placeholder" > {{
! field.fillingWay | | field.fillingWay = = ' calculate ' ? ' 计算值 ' : ' 请输入 '
}} < / text >
< text v-else : class = "['content-my-text-value', { 'field-high-light': field.highlight == 1 }]" > { {
field . valu e
} } < / text >
< / view >
< / view >
< / view >
< / templa te>
< / u-form >
< / up-collapse-i tem >
< / up-collapse >
<!-- < / view >
< / view > -- >
<!-- < / template > -- >
< / view >
< / scroll-view >
< u-button class = "btn-operation" type = "success" @click ="saveDetail()" > 保存样品数据 < / u -button >
@@ -192,10 +199,10 @@
< / template >
< 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 request from '@/nx/request'
import { calcAnalysisValue } from '@/nx/helper/calcAnalysisValue'
import { calcAnalysisValue , handleRoundFiveNumber , calcRowAnalysisValue , math } from '@/nx/helper/calcAnalysisValue'
import { number } from 'mathjs'
import AuncelSelectPopup from '@/components/sample/auncel-select-popup.vue'
import { getTenantId } from '@/defaultBaseUrl'
@@ -212,9 +219,8 @@ const scrollTop = ref(0) //tab标题的滚动条位置
const menuHeight = ref ( 0 ) // 左边菜单的高度
const menuItemHeight = ref ( 0 ) // 左边菜单item的高度
const weightDataIsToZero = ref ( false ) //重量数据是否归零
const currentSample = ref ( { } ) //当前样品
const currentSampleIndex = ref ( 0 ) // 预设当前项的值
let sampleDataList = [ ]
let sampleDataList = ref ( [ ] )
const title = ref ( '' )
const numKeyboardParam = reactive ( {
decimal : '-1' //数字键盘小数位数,-1为不限制
@@ -230,7 +236,6 @@ const currentAuncel = ref({
} )
let selectedField = ref ( { } )
const groupFieldIndex = ref ( '' ) //分组的索引
const leftList = ref ( [ ] )
const curSample = ref ( { } )
const curParameterTitle = ref ( '选择字段分类' )
const curParameterKey = ref ( '' )
@@ -249,7 +254,7 @@ const auncelSelector = ref(null)
// 计算属性
const confirmWeightDisabled = computed ( ( ) => {
if (
currentSample . value . sampleCode &&
currentSampleData . value . sampleCode &&
currentAuncel . value . weightStable === 1 &&
Number ( currentAuncel . value . weightData ) > 0
) {
@@ -257,12 +262,12 @@ const confirmWeightDisabled = computed(() => {
}
return true
} )
// 当前样品数据索引
const currentSampleDataIndex = computed ( ( ) => {
if ( sampleDataList . length > 0 ) {
return sampleDataList . findIndex ( item => item . businessAssayTaskDataId === currentSample. value . id )
// 当前样品数据
const currentSampleData = computed ( ( ) => {
if ( sampleDataList . value . length > 0 ) {
return sampleDataList . value [ currentSampleIndex . value ]
}
return - 1
return { }
} )
// 当前操作字段索引
const currentFieldKey = computed ( ( ) => {
@@ -316,15 +321,17 @@ const parameterClassifyChange = (v, a) => {
}
const fieldClick = ( field , key ) => {
myKeyboard . value . clearNum ( )
if ( field . fillingWay == 4 || ! field . fillingWay || field . fillingWay == 3 ) return
if ( field . fillingWay == 'input' || ! field . fillingWay || field . fillingWay == 'calculate' ) return
selectedField . value = field
groupFieldIndex . value = key
if ( myKeyboard . value ) {
myKeyboard . value . clearNum ( )
}
//判断小数位数
let decimalPosition = field . decimalPosition
if ( decimalPosition == null || decimalPosition < - 1 ) decimalPosition = - 1
numKeyboardParam . decimal = decimalPosition
if ( field . fillingWay == 2 ) {
if ( field . fillingWay == 'keyboard' ) {
listenDeviceData ( )
} else {
closeDeviceListener ( )
@@ -350,7 +357,7 @@ const autoNextField = () => {
//自动切换到下一个样品
const autoNextSample = ( ) => {
if ( left List. value . length <= currentSampleIndex . value + 1 ) return
if ( sampleData List. value . length <= currentSampleIndex . value + 1 ) return
const index = currentSampleIndex . value + 1
groupFieldIndex . value = ''
selectedField . value = { }
@@ -376,7 +383,6 @@ const switchSample = async (index, autoFlag) => {
// groupFieldIndex.value = groupFieldIndex.value.split('-')[0] + '-'
// }
uni . showLoading ( { title : '加载中...' } )
currentSample . value = leftList . value [ index ]
setValueToField ( )
autoGenerateCupNum ( )
setTimeout ( ( ) => {
@@ -413,7 +419,7 @@ const getElRect = (elClass, maxRetry = 50) => {
//读取样品明细字段
const getDetailFieldsAndStatus = autoSelectNextField => {
const taskDetailId = currentSample . value . id
const taskDetailId = currentSampleData . value . id
//读取回收率配置
loadConRecoveryList ( )
optionParameterClassify . value = arr //字段分类
@@ -619,29 +625,96 @@ const saveAuncelData = () => {
autoNextField ( )
} , 100 )
}
const dynamicFormData = { }
const saveDetail = async ( ) => {
//检查杯号
if ( ! checkBh ( ) ) return
let params = {
businessAssayTaskId : taskId . value ,
datas : sampleDataList
}
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 ( )
}
// 计算表格列平均值
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 ( ) {
let fields = fieldGroup . value . flatMap ( item => item . fields )
fields . forEach ( item => {
if ( sampleDataList [ currentSampleDataIndex . value ] . hasOwnProperty ( item . fieldIndex ) ) {
sampleDataList [ currentSampleData Index . value ] [ item . fieldIndex ] . value = item . value
if (
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 ) {
left List. value [ currentSampleIndex . value ] . cupNum = item . value
sampleData List. value [ currentSampleIndex . value ] . cupNum = item . value
}
} )
}
@@ -676,14 +749,14 @@ const autoGenerateCupNum = () => {
//第一杯
if ( current === 0 ) return
//取上一个样品的杯号
const sample = left List. value [ current - 1 ]
const sample = sampleData List. value [ current - 1 ]
cupNum = sample . cupNum
//杯号赋值到当前样品
putCupNum ( Number ( cupNum ) + 1 , current , Number ( cupNum ) )
}
const putCupNum = ( cupNum , sampleIndex , lastCupNum ) => {
left List. value [ sampleIndex ] . cupNum = cupNum
sampleData List. value [ sampleIndex ] . cupNum = cupNum
for ( const fields of fieldGroup . value ) {
if ( typeof fields === 'undefined' ) continue
//杯号
@@ -727,7 +800,7 @@ const putCupNum = (cupNum, sampleIndex, lastCupNum) => {
}
const loadConRecoveryList = ( ) => {
const conBaseSampleId = currentSample . value . conBaseSampleId
const conBaseSampleId = currentSampleData . value . conBaseSampleId
const rParam = {
pageNo : 1 ,
pageSize : - 1 ,
@@ -754,29 +827,60 @@ const loadConRecoveryList = () => {
} )
}
const getAssayTaskSampleList = businessAssayTaskId => {
leftList . value = [ ]
nx . $api . assayTask
. getAssayTaskDataList ( { businessAssayTaskId } )
. then ( res => {
leftList . value = res
currentSampleIndex . value = 0
currentSample . value = leftList . value [ 0 ]
} )
. catch ( err => {
console . error ( err )
} )
// 分析样品组
let assayGroups = ref ( [ ] )
const activeAssayTypeKey = ref ( '' )
const activeAssayTypeIndex = ref ( 0 )
//元素结果范围
let conRangeElementAnalysisList = [ ]
const currentAssayType = computed ( ( ) => {
return assayGroups . value . find ( item => item . value === activeAssayTypeKey . value )
} )
watch (
( ) => currentAssayType . value ,
( ) => {
sampleDataList . value = currentAssayType . value . tableData
fieldGroup . value = [ { open : true , fields : currentAssayType . value . columns , title : '样品分析' } ]
setValueToField ( )
// getDomHeight()
activeCollapses . value = fieldGroup . value . map ( ( _ , index ) => index )
}
)
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 || [ ]
async function getSampleAnalysisByTaskId ( businessAssayTaskId ) {
const data = await nx . $api . assayTask . getSampleAnalysisByTaskId ( businessAssayTaskId )
s ampleDataList = data . datas
let columns = data . columns . filter ( item => item . paramNo )
fieldGroup . value = [ { open : true , fields : columns , title : '样品分析' } ]
setValueToField ( )
title . value = '样品分析-任务指派单:' + data . businessAssayTasNo
getDomHeight ( )
autoNextField ( )
return {
value : group . analysisType ,
n ame : 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 ( ) {
@@ -788,7 +892,7 @@ function setValueToField() {
}
}
function getFieldValue ( field ) {
const fieldValue = sampleDataList [ currentSampleData Index . value ] [ field . fieldIndex ] . value
const fieldValue = sampleDataList . value [currentSampleIndex . value ] [ field . fieldIndex ] ? . value
if ( fieldValue ) {
return fieldValue
} else {
@@ -1008,8 +1112,8 @@ onLoad(param => {
lockOrientation ( 'landscape' )
if ( param . currentTaskId ) {
taskId . value = param . currentTaskId
getAssayTaskSampleList( taskId. value)
getSampleAnalysisByTaskId ( taskId . value )
// getAssayTaskSampleList( taskId. value)
getSampleAnalysisByTaskId ( )
}
loadFieldApiData ( fieldGroup . value )
listenNumKeyboard ( )
@@ -1112,7 +1216,7 @@ onBackPress(() => {
color : # c0c4cc ;
}
. content - left - scroll {
height : 60 vh ;
height : 68 vh ;
}
. content - right - scroll {
height : 68 vh ;