feat:元素校验范围

This commit is contained in:
houjunxiang
2025-11-12 10:19:30 +08:00
parent 970a8b8eae
commit 3a5acea5a3
2 changed files with 167 additions and 46 deletions

View File

@@ -352,3 +352,53 @@ export function groupByField(list, groupKey = 'groupDictionaryBusinessKey') {
// 转为数组 // 转为数组
return Array.from(groupMap.values()) return Array.from(groupMap.values())
} }
export function validateElementRange(fieldIndex, row, conRangeElementAnalysisList) {
if (!conRangeElementAnalysisList?.length) return null
const rangeElementAnalysis = conRangeElementAnalysisList.find(
ele => ele.dictionaryProjectId === row[fieldIndex]?.dicId && row[fieldIndex]['type'] === 'project'
)
if (!rangeElementAnalysis) return null
const val = row[fieldIndex]?.value
if (val == '' || val == null) return null
const value = Number(val)
let result = { promptType: '', promptMsg: '' }
switch (Number(rangeElementAnalysis.rangeType)) {
case 1:
//如果值小于最小警告值或者大于最大警告值,则校验不通过
if (value < rangeElementAnalysis.minimumWarningValue || value > rangeElementAnalysis.maximumWarningValue) {
result.promptType = 'warning'
result.promptMsg = `警告:值超出范围(${rangeElementAnalysis.minimumWarningValue} ~ ${rangeElementAnalysis.maximumWarningValue}`
}
break
case 2:
//如果值小于最小限制值或者大于最大限制值,则校验不通过
if (value < rangeElementAnalysis.minimumValue || value > rangeElementAnalysis.maximumValue) {
result.promptType = 'error'
result.promptMsg = `错误:值超出范围(${rangeElementAnalysis.minimumValue} ~ ${rangeElementAnalysis.maximumValue}`
}
break
case 3:
//如果值小于最小限制值或者大于最大限制值,则校验不通过
if (value < rangeElementAnalysis.minimumValue || value > rangeElementAnalysis.maximumValue) {
result.promptType = 'error'
result.promptMsg = `错误:值超出范围(${rangeElementAnalysis.minimumValue} ~ ${rangeElementAnalysis.maximumValue}`
} else if (
(rangeElementAnalysis.minimumValue < value && value < rangeElementAnalysis.minimumWarningValue) ||
(rangeElementAnalysis.maximumWarningValue < value && value <= rangeElementAnalysis.maximumValue)
) {
result.promptType = 'warning'
result.promptMsg = `警告:值超出范围(${rangeElementAnalysis.minimumWarningValue} ~ ${rangeElementAnalysis.maximumWarningValue}`
}
break
default:
return null
}
return result
}

View File

@@ -105,6 +105,18 @@
确认采集 确认采集
</u-button> </u-button>
</view> </view>
<view v-if="selectedField.fillingWay === 'input'" class="p8">
<up-textarea v-model="inputValue" placeholder="请输入内容"></up-textarea>
<view class="x-c mt20 pl100 pr100">
<up-button @click="handleResetInputValue" style="width: 30%" :plain="true" text="清空"></up-button>
<up-button
@click="selectedField.value = inputValue"
style="width: 30%"
type="success"
text="确认"
></up-button>
</view>
</view>
</u-col> </u-col>
<u-col span="3"> <u-col span="3">
<view> <view>
@@ -122,39 +134,41 @@
: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 ref="collapseRef" :value="activeCollapses" :border="false">
<template v-for="(fields, groupIndex) in currentGroup"> <template v-for="(fields, groupIndex) in currentGroup">
<up-collapse-item v-if="fields.label !== '全部'" :title="fields.label"> <up-collapse-item v-if="fields.label !== '全部'">
<view <template #title>
class="form-item-my" <text class="font-bold">{{ fields.label }}</text>
v-for="(field, fieldIndex) in fields.fields" </template>
@click="fieldClick(field, groupIndex + '-' + fieldIndex)" <template v-for="(field, fieldIndex) in fields.fields" :key="groupIndex + '-' + fieldIndex">
:key="groupIndex + '-' + fieldIndex"
v-show="field.hidden != 1"
:class="{
'selected-field': groupFieldIndex === groupIndex + '-' + fieldIndex,
'disabled-field': !field.isEdit
}"
>
<view <view
:class="['label-my', { 'label-high-light': field.highlight == 1 }]" class="form-item-my"
v-html="field.title" @click="fieldClick(field, groupIndex + '-' + fieldIndex)"
></view> v-show="field.hidden != 1"
<view class="content-my"> :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个input1个picker. 如果是select渲染2个组件1个input1个picker.
field.valueText用于显示picker选中的文本 field.valueText用于显示picker选中的文本
1键盘输入2天平3自动计算4文本输入 1键盘输入2天平3自动计算4文本输入
--> -->
<u-input <!-- <u-input
border="bottom" border="bottom"
style="width: 120px" style="width: 120px"
v-if="field.fillingWay == 'input'" v-if="field.fillingWay == 'input'"
v-model="field.value" v-model="field.value"
placeholder="请输入" 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-if="field.valueText">{{ field.valueText }}</text>
<text v-else>请选择</text> <text v-else>请选择</text>
<u-icon name="arrow-down" size="20"></u-icon> <u-icon name="arrow-down" size="20"></u-icon>
@@ -167,19 +181,26 @@
@cancel="field.showPicker = false" @cancel="field.showPicker = false"
@confirm="event => dicPickerConfirm(event, field)" @confirm="event => dicPickerConfirm(event, field)"
/> --> /> -->
<!--普通输入框 使用文本显示--> <!--普通输入框 使用文本显示-->
<view class="content-my-text" v-if="field.dataType != 'select' && field.fillingWay != 'input'"> <view class="content-my-text" v-if="field.dataType != 'select'">
<text v-if="!field.value" class="content-my-text-placeholder">{{ <text v-if="!field.value" class="content-my-text-placeholder">{{
!field.fillingWay || field.fillingWay == 'calculate' ? '计算值' : '请输入' !field.fillingWay || field.fillingWay == 'calculate' ? '计算值' : '请输入'
}}</text> }}</text>
<text <text
v-else v-else
:class="['content-my-text-value', { 'field-high-light': field.highlight == 1 }]" :class="['content-my-text-value', { 'field-high-light': field.highlight == 1 }]"
>{{ field.value }}</text >{{ field.value }}</text
> >
</view>
</view> </view>
</view> </view>
</view> <view
v-if="field.validation"
class="fs12"
:class="field.validation?.promptType === 'warning' ? 'valid-warning' : 'valid-error'"
>{{ field.validation?.promptMsg }}</view
>
</template>
</up-collapse-item> </up-collapse-item>
</template> </template>
</up-collapse> </up-collapse>
@@ -211,7 +232,8 @@ import {
handleRoundFiveNumber, handleRoundFiveNumber,
calcRowAnalysisValue, calcRowAnalysisValue,
math, math,
groupByField groupByField,
validateElementRange
} from '@/nx/helper/calcAnalysisValue' } 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'
@@ -255,7 +277,11 @@ const busSubCSampleId = ref('')
let fieldGroup = ref([]) let fieldGroup = ref([])
const collaHeights = ref([]) const collaHeights = ref([])
const cupNumKey = '杯号' const cupNumKey = '杯号'
const inputValue = ref('')
function handleResetInputValue() {
inputValue.value = ''
}
// refs // refs
const myKeyboard = ref(null) const myKeyboard = ref(null)
const auncelSelector = ref(null) const auncelSelector = ref(null)
@@ -312,7 +338,10 @@ const parameterClassifyChange = v => {
} }
const fieldClick = (field, key) => { const fieldClick = (field, key) => {
if (!field.isEdit || field.fillingWay === 'input') return if (!field.isEdit) return
if (field.fillingWay === 'input') {
inputValue.value = field.value
}
selectedField.value = field selectedField.value = field
groupFieldIndex.value = key groupFieldIndex.value = key
if (myKeyboard.value) { if (myKeyboard.value) {
@@ -567,7 +596,27 @@ const checkBh = () => {
} }
return true return true
} }
const checkRange = async () => {
for (const g of fieldGroup.value) {
for (const f of g.fields) {
if (f.validation) {
if (f.validation.promptType === 'error') {
nx.$helper.showToast({
title: '存在范围校验错误,请修正后再保存!',
icon: 'error',
duration: 2000
})
return false
}
if (f.validation.promptType === 'warning') {
const confirm = await tools.showPromiseModal('提示', '检测到范围警告,是否继续保存?')
return confirm
}
}
}
}
return true // 无问题,通过
}
const saveAuncelData = () => { const saveAuncelData = () => {
//保存数据 //保存数据
if (!weightDataIsToZero.value) { if (!weightDataIsToZero.value) {
@@ -625,6 +674,8 @@ const dynamicFormData = {}
const saveDetail = async () => { const saveDetail = async () => {
//检查杯号 //检查杯号
if (!checkBh()) return if (!checkBh()) return
// 检查范围校验
if (!(await checkRange())) return
setValueToSample() setValueToSample()
let params = { let params = {
businessAssayTaskId: taskId.value businessAssayTaskId: taskId.value
@@ -634,7 +685,7 @@ const saveDetail = async () => {
if (activeAssayTypeKey.value === 'kby' || activeAssayTypeKey.value === 'by') { if (activeAssayTypeKey.value === 'kby' || activeAssayTypeKey.value === 'by') {
// 处理其他页签的输入变化 // 处理其他页签的输入变化
const configInfomation = currentAssayType.value.configQCSampleMethodInfo const configInfomation = currentAssayType.value.configQCSampleMethodInfo
const row = sampleDataList.value[currentSampleIndex.value] const row = currentSampleData.value
configInfomation.forEach(item => { configInfomation.forEach(item => {
const sourceKey = item.source const sourceKey = item.source
const sourceValue = row[sourceKey] const sourceValue = row[sourceKey]
@@ -657,7 +708,7 @@ const saveDetail = async () => {
analysisType: item.value analysisType: item.value
})) }))
} else { } else {
const datas = sampleDataList.value[currentSampleIndex.value] const datas = currentSampleData.value
params.assayTaskAnalysisDataList = [{ datas: [datas], analysisType: activeAssayTypeKey.value }] params.assayTaskAnalysisDataList = [{ datas: [datas], analysisType: activeAssayTypeKey.value }]
} }
@@ -703,14 +754,14 @@ 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 ( if (
sampleDataList.value[currentSampleIndex.value].hasOwnProperty(item.fieldIndex) && currentSampleData.value.hasOwnProperty(item.fieldIndex) &&
nx.$test.object(sampleDataList.value[currentSampleIndex.value][item.fieldIndex]) nx.$test.object(currentSampleData.value[item.fieldIndex])
) { ) {
sampleDataList.value[currentSampleIndex.value][item.fieldIndex].value = item.value currentSampleData.value[item.fieldIndex].value = item.value
} }
// 初始化的时候保存杯号到样品中后续自动生成杯号用 // 初始化的时候保存杯号到样品中后续自动生成杯号用
if (item.title === cupNumKey && currentSampleIndex.value == 0) { if (item.title === cupNumKey && currentSampleIndex.value == 0) {
sampleDataList.value[currentSampleIndex.value].cupNum = item.value currentSampleData.value.cupNum = item.value
} }
}) })
} }
@@ -828,7 +879,7 @@ let assayGroups = ref([])
const activeAssayTypeKey = ref('') const activeAssayTypeKey = ref('')
const activeAssayTypeIndex = ref(0) const activeAssayTypeIndex = ref(0)
//元素结果范围 //元素结果范围
let conRangeElementAnalysisList = [] let conRangeElementAnalysisList = ref([])
const currentAssayType = computed(() => { const currentAssayType = computed(() => {
return assayGroups.value.find(item => item.value === activeAssayTypeKey.value) return assayGroups.value.find(item => item.value === activeAssayTypeKey.value)
}) })
@@ -856,6 +907,21 @@ const currentGroup = computed(() => {
return fieldGroup.value.filter(g => g.value === curParameterKey.value) return fieldGroup.value.filter(g => g.value === curParameterKey.value)
} }
}) })
watch(
() => currentGroup.value,
() => {
fieldGroup.value.forEach(item => {
item.fields.forEach(field => {
const validation = validateElementRange(
field.fieldIndex,
currentSampleData.value,
conRangeElementAnalysisList.value
)
field.validation = validation
})
})
}
)
const collapseRef = ref() const collapseRef = ref()
const activeCollapses = ref([]) const activeCollapses = ref([])
function handleAssayTypeChange({ index, value }) { function handleAssayTypeChange({ index, value }) {
@@ -893,7 +959,7 @@ async function getSampleAnalysisByTaskId() {
if (!activeAssayTypeKey.value) { if (!activeAssayTypeKey.value) {
activeAssayTypeKey.value = assayGroups.value.length > 0 ? assayGroups.value[0].value : '' activeAssayTypeKey.value = assayGroups.value.length > 0 ? assayGroups.value[0].value : ''
} }
conRangeElementAnalysisList = configAssayMethodProjectRangeList || [] conRangeElementAnalysisList.value = configAssayMethodProjectRangeList || []
} }
// 设置字段值 // 设置字段值
function setValueToField() { function setValueToField() {
@@ -905,7 +971,7 @@ function setValueToField() {
} }
} }
function getFieldValue(field) { function getFieldValue(field) {
const fieldValue = sampleDataList.value[currentSampleIndex.value][field.fieldIndex]?.value const fieldValue = currentSampleData.value[field.fieldIndex]?.value
if (fieldValue) { if (fieldValue) {
return fieldValue return fieldValue
} else { } else {
@@ -1176,8 +1242,7 @@ onBackPress(() => {
.form-item-my { .form-item-my {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 10px; min-height: 35px;
height: 35px;
font-size: 13px; font-size: 13px;
border-bottom: 1px solid #dcdcdc; border-bottom: 1px solid #dcdcdc;
} }
@@ -1233,6 +1298,12 @@ onBackPress(() => {
.content-right-scroll { .content-right-scroll {
height: 68vh; height: 68vh;
} }
.valid-warning {
color: orange;
}
.valid-error {
color: red;
}
.u-tab-item { .u-tab-item {
display: flex; display: flex;