feat: 增加Sample Type、Sample、QC Flags字段,及相应处理,重构部分代码

This commit is contained in:
Xu Zhimeng 2025-01-02 17:28:16 +08:00
parent 791271c747
commit 8bb9016a42
2 changed files with 357 additions and 164 deletions

View File

@ -0,0 +1,68 @@
export const SampleTypeOptions = [
{
label: 'All',
value: 'All'
},
{
label: 'Gamma',
value: 'Gamma'
},
{
label: 'Beta',
value: 'Beta'
}
]
export const SampleMap = {
All: ['P', 'B', 'G', 'C'],
Gamma: ['P', 'G'],
Beta: ['B', 'C']
}
export const MenuNameMap = {
P: 'Particulate',
G: 'Noble Gas HPGe',
B: 'Noble Gas Beta-Gamma',
C: 'Self-Station'
}
export const QcFlagOptions = {
P: [
{ label: 'acq_time (h)', isArray: false, value: 18, prop: 'acqTime' },
{ label: 'airFlow (m3/h)', isArray: false, value: 500, prop: 'airFlow' },
{ label: 'decay_time (h)', isArray: false, value: 26.4, prop: 'decayTime' },
{ label: 'samp_vol (m3)', isArray: false, value: 10800, prop: 'sampVol' },
{ label: 'Be7-FWHM (keV)', isArray: false, value: 1.7, prop: 'be7FWHM' },
{
label: 'Ba140-MDC (uBq/m3)',
isArray: false,
value: 30,
prop: 'ba140MDC'
},
{ label: 'col_time (h)', isArray: true, value: [21.6, 26.4], prop: 'colTime' }
],
B: [
{ label: 'Xenon Volume (ml)', isArray: false, value: 0.2, prop: 'xeVol' },
{ label: 'Collection Time (h)', isArray: true, value: [6.0, 24.0], prop: 'colTime' },
{ label: 'Acqusition Time (h)', isArray: true, value: [6.0, 24.0], prop: 'acqTime' },
{ label: 'MDC for Xe133 (mBq/m3)', isArray: true, value: [0.001, 5], prop: 'xe133MDC' },
{ label: 'Xe131m Flag', isArray: false, value: 1, disabled: true, prop: 'xe131mFlag' },
{ label: 'Xe133m Flag', isArray: false, value: 1, disabled: true, prop: 'xe133mFlag' },
{ label: 'Xe133 Flag', isArray: false, value: 1, disabled: true, prop: 'xe133Flag' },
{ label: 'Xe135 Flag', isArray: false, value: 1, disabled: true, prop: 'xe135Flag' }
],
G: [
{ label: 'airFlow (m3/h)', isArray: false, value: 0.4, prop: 'airFlow' },
{ label: 'decay_time (h)', isArray: false, value: 10.0, prop: 'decayTime' },
{ label: 'samp_vol (m3)', isArray: false, value: 10, prop: 'sampVol' },
{ label: 'Xe133-MDC (uBq/m3)', isArray: false, value: 1000, prop: 'xe133MDC' },
{ label: 'acq_time (h)', isArray: true, value: [16.0, 24.0], prop: 'acqTime' },
{ label: 'col_time (h)', isArray: true, value: [21.6, 24.0], prop: 'colTime' },
],
C: [
{ label: 'Xe131m Flag', isArray: false, value: 1, disabled: true, prop: 'xe131mFlag' },
{ label: 'Xe133m Flag', isArray: false, value: 1, disabled: true, prop: 'xe133mFlag' },
{ label: 'Xe133 Flag', isArray: false, value: 1, disabled: true, prop: 'xe133Flag' },
{ label: 'Xe135 Flag', isArray: false, value: 1, disabled: true, prop: 'xe135Flag' }
]
}

View File

@ -154,6 +154,8 @@
@showSizeChange="handleSizeChange" @showSizeChange="handleSizeChange"
/> />
</div> </div>
<!-- 新增/编辑规则弹窗 -->
<a-modal <a-modal
:title="isAdd ? 'Add Rule' : 'Edit Rule'" :title="isAdd ? 'Add Rule' : 'Edit Rule'"
:width="800" :width="800"
@ -161,52 +163,74 @@
:maskClosable="false" :maskClosable="false"
@cancel="onCancel" @cancel="onCancel"
> >
<a-form :form="form" :label-col="labelCol" :wrapper-col="wrapperCol"> <a-form-model
<a-form-item label="Name"> ref="form"
<a-input :model="formVal"
v-decorator="[ :label-col="labelCol"
'name', :wrapper-col="wrapperCol"
{ style="max-height: calc(100vh - 341px); overflow: hidden auto"
rules: [{ required: true, message: 'Please input name!' }], >
initialVale: this.formVal.name, <a-form-model-item label="Name" prop="name" :rules="[{ required: true, message: 'Please input name!' }]">
}, <a-input v-model="formVal.name" />
]" </a-form-model-item>
/>
</a-form-item>
<a-form-item label="Source"> <a-form-model-item label="Source" prop="source" :rules="[{ required: true, message: 'Please select source!' }]">
<dic-select <dic-select type="checkbox" dictCode="alarm_analyse_rule_source" v-model="formVal.source" />
type="checkbox" </a-form-model-item>
dictCode="alarm_analyse_rule_source" <a-row>
v-decorator="[ <a-col :span="12">
'source', <a-form-model-item
{ label="Sample Type"
rules: [{ required: true }], prop="sampleType"
initialVale: this.formVal.source, :rules="[{ required: true, message: 'Please select sample type!' }]"
}, :label-col="{ span: 8 }"
]" :wrapper-col="{ span: 16 }"
/> >
</a-form-item> <a-select v-model="formVal.sampleType" @change="handleSampleTypeChange" style="width: 100%">
<a-form-item label="Station"> <a-select-option v-for="item in SampleTypeOptions" :key="item.value" :value="item.value">
{{ item.label }}
</a-select-option>
</a-select>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item
label="Sample"
prop="sample"
:rules="[{ required: true, message: 'Please select sample!' }]"
:label-col="{ span: 8 }"
:wrapper-col="{ span: 12 }"
>
<a-select v-model="formVal.sample" @change="handleSampleChange" style="width: 100%">
<a-select-option v-for="item in sampleList" :key="item" :value="item">
{{ item }}
</a-select-option>
</a-select>
</a-form-model-item>
</a-col>
</a-row>
<a-form-model-item
label="Station"
prop="station"
:rules="[{ required: true, message: 'Please select station!' }]"
>
<a-select <a-select
class="form-select" class="form-select"
mode="multiple" mode="multiple"
placeholder="select..." placeholder="select..."
:filter-option="filterOption" :filter-option="filterOption"
show-arrow show-arrow
:options="stationOptions" :options="filteredStationList"
v-decorator="[ v-model="formVal.station"
'station',
{
rules: [{ required: true, message: 'Please select station' }],
initialVale: this.formVal.station,
},
]"
> >
<img slot="suffixIcon" src="@/assets/images/global/select-down.png" alt="" /> <img slot="suffixIcon" src="@/assets/images/global/select-down.png" alt="" />
</a-select> </a-select>
</a-form-item> </a-form-model-item>
<a-form-item label="Nuclide"> <a-form-model-item
label="Nuclide"
prop="nuclide"
:rules="[{ required: true, message: 'Please select nuclide!' }]"
>
<a-select <a-select
class="form-select" class="form-select"
mode="multiple" mode="multiple"
@ -215,75 +239,85 @@
:filter-option="filterOption" :filter-option="filterOption"
show-arrow show-arrow
:options="nuclideOptions" :options="nuclideOptions"
v-decorator="[ v-model="formVal.nuclide"
'nuclide',
{
rules: [{ required: true, message: 'Please select nuclide' }],
initialVale: this.formVal.nuclide,
},
]"
> >
<img slot="suffixIcon" src="@/assets/images/global/select-down.png" alt="" /> <img slot="suffixIcon" src="@/assets/images/global/select-down.png" alt="" />
</a-select> </a-select>
</a-form-item> </a-form-model-item>
<a-form-item label="Qualifier"> <a-form-model-item
<dic-select label="Coefficient"
type="checkbox" prop="coefficient"
dictCode="spectral_qualifier" :rules="[{ required: true, message: 'Please input coefficient!' }]"
v-decorator="[ >
'qualifier', <a-input type="number" v-model="formVal.coefficient"></a-input>
{ </a-form-model-item>
rules: [{ required: true }], <a-form-model-item v-if="formVal.sample" label="Qc Flags" style="margin-bottom: 0">
initialVale: this.formVal.qualifier, <a-row :gutter="10">
}, <a-col
]" class="qc-item"
/> :span="item.disabled ? 6 : item.isArray ? 24 : 12"
</a-form-item> v-for="(item, index) in qcFlagList"
<a-form-item label="Condition"> :key="index"
>
<a-checkbox v-model="item.checked"></a-checkbox>
<span>{{ item.label }}</span>
<!-- 如果有两个值 -->
<template v-if="item.isArray">
<a-input type="number" v-model="item.value[0]" placeholder="min" :readOnly="!item.checked"></a-input>
<a-input type="number" v-model="item.value[1]" placeholder="max" :readOnly="!item.checked"></a-input>
</template>
<template v-else>
<a-input
v-if="!item.disabled"
type="number"
v-model="item.value"
:readOnly="item.disabled || !item.checked"
placeholder="请输入..."
/>
</template>
</a-col>
</a-row>
</a-form-model-item>
<a-form-model-item
label="Qualifier"
prop="qualifier"
:rules="[{ required: true, message: 'Please select qualifier!' }]"
>
<dic-select type="checkbox" dictCode="spectral_qualifier" v-model="formVal.qualifier" />
</a-form-model-item>
<a-form-model-item
label="Condition"
prop="condition"
:rules="[{ required: true, message: 'Please select condition!' }]"
>
<dic-select <dic-select
type="checkbox" type="checkbox"
layout="vertical" layout="vertical"
dictCode="alarm_analyse_rule_condition" dictCode="alarm_analyse_rule_condition"
v-decorator="[ v-model="formVal.condition"
'condition',
{
rules: [{ required: true }],
initialVale: this.formVal.condition,
},
]"
> >
</dic-select> </dic-select>
</a-form-item> </a-form-model-item>
<a-form-item label="Contact Group"> <a-form-model-item
label="Contact Group"
prop="contactGroup"
:rules="[{ required: true, message: 'Please select contact group!' }]"
>
<a-select <a-select
class="form-select" class="form-select"
:options="contactGroupOptions" :options="contactGroupOptions"
show-arrow show-arrow
allowClear allowClear
placeholder="select..." placeholder="select..."
v-decorator="[ v-model="formVal.contactGroup"
'contactGroup',
{
rules: [{ required: true }],
initialVale: this.formVal.contactGroup,
},
]"
> >
<img slot="suffixIcon" src="@/assets/images/global/select-down.png" alt="" /> <img slot="suffixIcon" src="@/assets/images/global/select-down.png" alt="" />
</a-select> </a-select>
</a-form-item> </a-form-model-item>
<a-form-item label="Remark"> <a-form-model-item label="Remark">
<a-input <a-input type="textarea" v-model="formVal.remark" />
type="textarea" </a-form-model-item>
v-decorator="[ </a-form-model>
'remark',
{
initialVale: this.formVal.remark,
},
]"
/>
</a-form-item>
</a-form>
<template slot="footer"> <template slot="footer">
<a-space class="operators" :size="20"> <a-space class="operators" :size="20">
<a-button type="success" @click="onSave">Save</a-button> <a-button type="success" @click="onSave">Save</a-button>
@ -291,12 +325,32 @@
</a-space> </a-space>
</template> </template>
</a-modal> </a-modal>
<!-- 新增/编辑规则弹窗 -->
</div> </div>
</template> </template>
<script> <script>
import { getAction, postAction, httpAction, deleteAction, putAction } from '@/api/manage' import { getAction, postAction, httpAction, deleteAction, putAction } from '@/api/manage'
import DicSelect from '../../components/dicSelect.vue' import DicSelect from '../../components/dicSelect.vue'
import { MenuNameMap, QcFlagOptions, SampleMap, SampleTypeOptions } from './config'
import { cloneDeep } from 'lodash'
const InitialFormVal = {
name: '',
source: null,
station: undefined,
nuclide: undefined,
qualifier: null,
condition: null,
contactGroup: null,
remark: '',
// Sample TypeSampleCoefficient
sampleType: null,
sample: null,
coefficient: 1.0,
}
export default { export default {
components: { components: {
DicSelect, DicSelect,
@ -339,18 +393,14 @@ export default {
wrapperCol: { span: 18 }, wrapperCol: { span: 18 },
form: this.$form.createForm(this), form: this.$form.createForm(this),
contactGroupOptions: [], contactGroupOptions: [],
formVal: { formVal: cloneDeep(InitialFormVal),
name: '',
source: null,
station: undefined,
nuclide: undefined,
qualifier: null,
condition: null,
contactGroup: undefined,
remark: '',
},
monitorList: [], monitorList: [],
currId: '', currId: '',
SampleTypeOptions,
sampleList: [],
qcFlagList: [],
filteredStationList: [],
} }
}, },
created() { created() {
@ -360,29 +410,35 @@ export default {
this.getAlarmRulesPage() this.getAlarmRulesPage()
}, },
methods: { methods: {
getStationList() { async getStationList() {
getAction('/webStatistics/findStationList', { menuName: '' }).then((res) => { this.stationOptions = await this.stationRequest('')
if (res.success) { },
if (res.result.length > 0) {
this.stationOptions = res.result.map((item) => { async stationRequest(menuName) {
return { try {
label: item.stationCode, const { success, result } = await getAction('/webStatistics/findStationList', { menuName })
value: `${item.stationId}`, if (success) {
} return result.map((item) => {
}) return {
} else { label: item.stationCode,
this.stationOptions = [] value: `${item.stationId}`,
} }
})
} else { } else {
this.$message.warning('This operation fails. Contact your system administrator') this.$message.warning('This operation fails. Contact your system administrator')
return []
} }
}) } catch (error) {
this.$message.error(error)
return []
}
}, },
getNuclideList() { getNuclideList() {
getAction('/sys/defaultNuclide/allName', { useType: 2 }).then((res) => { getAction('/sys/defaultNuclide/allName', { useType: 2 }).then((res) => {
if (res.success) { if (res.success) {
if (res.result.length > 0) { if (res.result.length > 0) {
this.nuclideOptions = res.result.map((item) => { this.nuclideOptions = Array.from(new Set(res.result)).map((item) => {
return { return {
label: item, label: item,
value: item, value: item,
@ -399,10 +455,32 @@ export default {
handleAdd() { handleAdd() {
this.isAdd = true this.isAdd = true
this.visible = true this.visible = true
this.formVal = cloneDeep(InitialFormVal)
this.sampleList = []
this.qcFlagList = []
this.filteredStationList = []
}, },
filterOption(input, option) { filterOption(input, option) {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
}, },
// Sample Type
handleSampleTypeChange() {
this.sampleList = SampleMap[this.formVal.sampleType]
this.formVal.sample = undefined
this.formVal.station = undefined
this.filteredStationList = []
},
// sample
async handleSampleChange() {
this.qcFlagList = QcFlagOptions[this.formVal.sample]
this.filteredStationList = []
this.formVal.station = undefined
this.filteredStationList = await this.stationRequest(MenuNameMap[this.formVal.sample])
},
onStationChange(val) { onStationChange(val) {
this.queryParams.station = val this.queryParams.station = val
}, },
@ -435,28 +513,42 @@ export default {
this.ipagination.current = 1 this.ipagination.current = 1
this.getAlarmRulesPage() this.getAlarmRulesPage()
}, },
editItem(id) { async editItem(id) {
this.currId = id try {
getAction('/alarmAnalysisRule/finInfo', { id }).then((res) => { this.currId = id
if (res.success) { const { success, result, message } = await getAction('/alarmAnalysisRule/finInfo', { id })
if (success) {
this.isAdd = false this.isAdd = false
this.visible = true this.visible = true
this.$nextTick(() => { const { sourceChecked, qualifierChecked, conditionChecked, stationChecked, nuclidesChecked } = result
this.form.setFieldsValue({ this.formVal = {
name: res.result.name, ...result,
source: res.result.sourceChecked.join(','), station: stationChecked,
station: res.result.stationChecked, nuclide: nuclidesChecked,
nuclide: res.result.nuclidesChecked, source: sourceChecked.join(','),
qualifier: res.result.qualifierChecked.join(','), qualifier: qualifierChecked.join(','),
condition: res.result.conditionChecked.join(','), condition: conditionChecked.join(','),
contactGroup: res.result.contactGroup, }
remark: res.result.remark,
}) this.sampleList = SampleMap[this.formVal.sampleType]
this.qcFlagList = this.qcFlagList = QcFlagOptions[this.formVal.sample].map((item) => {
const val = this.formVal[item.prop]
const hasVal = val !== null && val !== undefined
return {
...item,
checked: hasVal,
value: hasVal ? val : item.value,
}
}) })
this.filteredStationList = await this.stationRequest(MenuNameMap[this.formVal.sample])
} else { } else {
this.$message.warning('This operation fails. Contact your system administrator') this.$message.warning('This operation fails. Contact your system administrator')
console.log(message)
} }
}) } catch (error) {
console.log(error)
}
}, },
deleteItem(id) { deleteItem(id) {
let _this = this let _this = this
@ -515,47 +607,70 @@ export default {
} }
}) })
}, },
onSave() { async onSave() {
this.form.validateFields((err, values) => { try {
if (!err) { await this.$refs.form.validate()
let params = {
conditions: values.condition, const qcFlagsHasBlank = this.qcFlagList.some(({ isArray, value, checked }) => {
name: values.name, return checked && (!value || (isArray && value.some((v) => !v)))
remark: values.remark, })
stations: values.station.join(','), if (qcFlagsHasBlank) {
source: values.source, this.$message.warning('Please fill in the QC Flag value')
nuclides: values.nuclide.join(','), return
contactGroup: values.contactGroup, }
spectralQualifier: values.qualifier,
} const qcFlags = this.qcFlagList.reduce((acc, { prop, value, isArray, checked }) => {
if (this.isAdd) { const val = checked ? (isArray ? value.join(',') : value) : null
postAction('/alarmAnalysisRule/add', params).then((res) => { acc[prop] = val
if (res.success) { return acc
this.visible = false }, {})
this.form.resetFields()
this.$message.success('success') // qc flags
this.getAlarmRulesPage() Object.values(QcFlagOptions).forEach((v) => {
} else { v.forEach((item) => {
this.$message.warning('This operation fails. Contact your system administrator') this.formVal[item.prop] = null
} })
}) })
const { station, nuclide, qualifier, condition } = this.formVal
const params = {
...this.formVal,
nuclide: undefined,
station: undefined,
condition: undefined,
spectralQualifier: qualifier,
conditions: condition,
stations: station.join(','),
nuclides: nuclide.join(','),
...qcFlags,
}
if (this.isAdd) {
const { success } = await postAction('/alarmAnalysisRule/add', params)
if (success) {
this.visible = false
this.$refs.form.resetFields()
this.$message.success('success')
this.getAlarmRulesPage()
} else { } else {
httpAction('/alarmAnalysisRule/edit', { ...params, id: this.currId }, 'put').then((res) => { this.$message.warning('This operation fails. Contact your system administrator')
if (res.success) { }
this.visible = false } else {
this.form.resetFields() const { success } = await httpAction('/alarmAnalysisRule/edit', { ...params, id: this.currId }, 'put')
this.$message.success('success') if (success) {
this.getAlarmRulesPage() this.visible = false
} else { this.$refs.form.resetFields()
this.$message.warning('This operation fails. Contact your system administrator') this.$message.success('success')
} this.getAlarmRulesPage()
}) } else {
this.$message.warning('This operation fails. Contact your system administrator')
} }
} }
}) } catch (error) {
console.log(error)
}
}, },
onCancel() { onCancel() {
this.form.resetFields() this.$refs.form.resetFields()
this.visible = false this.visible = false
}, },
}, },
@ -779,4 +894,14 @@ export default {
} }
} }
} }
.qc-item {
display: flex;
align-items: center;
gap: 8px;
span {
flex-shrink: 0;
}
}
</style> </style>