From 339de35256661dcbe04cf3862cb5bab170f0cb10 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期四, 27 八月 2026 21:59:33 +0800
Subject: [PATCH] fix(test): preserve hidden configuration facts
---
src/api/tests.ts | 2
src/views/TestCreate.vue | 138 +++++----------------------------------------
2 files changed, 17 insertions(+), 123 deletions(-)
diff --git a/src/api/tests.ts b/src/api/tests.ts
index c7df4ef..967ca14 100644
--- a/src/api/tests.ts
+++ b/src/api/tests.ts
@@ -40,7 +40,7 @@
minValue: number | null
maxValue: number | null
unit: 'A' | 'V' | 'Ah' | 'Wh' | '℃'
- severity: 'WARNING'
+ severity: string
}
export interface TestConfigurationPayload {
diff --git a/src/views/TestCreate.vue b/src/views/TestCreate.vue
index 4d22b64..6d3bfb7 100644
--- a/src/views/TestCreate.vue
+++ b/src/views/TestCreate.vue
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'
-import { ElMessage, ElMessageBox } from 'element-plus'
+import { ElMessage } from 'element-plus'
import { useRoute, useRouter } from 'vue-router'
import {
createTest,
@@ -9,6 +9,7 @@
updateTest,
type TestConfigurationDetail,
type TestConfigurationOptions,
+ type TestBatteryPayload,
type TestPlanStepPayload,
} from '@/api/tests'
@@ -21,6 +22,7 @@
cabinetChannel: number | null
collector: number | null
expectedBarcode: string | null
+ preservedFields: TestBatteryPayload['fields']
temperature1: string
temperature2: string
temperature3: string
@@ -34,7 +36,6 @@
interface CustomChannelColumn {
key: string
label: string
- fieldName: string
}
interface BatteryGroupOption {
@@ -50,6 +51,7 @@
min: string
max: string
unit: 'A' | 'V' | 'Ah' | 'Wh' | '℃'
+ severity: string
}
const router = useRouter()
@@ -66,7 +68,6 @@
const monitorTimeoutMinutes = ref(30)
let batteryKey = 1
let thresholdKey = 1
-let customChannelKey = 1
const form = reactive({
name: '',
@@ -81,7 +82,6 @@
const testTypes = ref<Array<{ id: number; name: string }>>([])
const ownersLoading = ref(false)
const testTypesLoading = ref(false)
-const sensorChannels = Array.from({ length: 12 }, (_, index) => `S-${String(index + 1).padStart(2, '0')}`)
const thresholdTypes: Array<{
label: string
value: string
@@ -95,13 +95,7 @@
{ label: '检测柜返回项(待现场验证)', value: 'CABINET_RETURN', unit: 'V' as const, disabled: true },
]
const fixedSensorFields = ['temperature1', 'temperature2', 'temperature3', 'positive1', 'positive2', 'negative1', 'negative2'] as const
-type FixedSensorField = typeof fixedSensorFields[number]
-const reservedChannelLabels = ['主温度通道', '温度通道 2', '温度通道 3', '正电位主通道', '正电位通道 2', '负电位主通道', '负电位通道 2']
const customChannelColumns = ref<CustomChannelColumn[]>([])
-const fixedFieldNames: Record<FixedSensorField, string> = {
- temperature1: 'temperature1', temperature2: 'temperature2', temperature3: 'temperature3',
- positive1: 'positive1', positive2: 'positive2', negative1: 'negative1', negative2: 'negative2',
-}
const batteryGroupOptions = ref<BatteryGroupOption[]>([])
const cabinetOptions = computed(() => {
const cabinets = new Map<number, string>()
@@ -118,7 +112,7 @@
function createBatteryRow(batteryNo = '', groupId: number | null = null): BatteryRow {
return {
key: batteryKey++, selected: false, groupId, batteryNo, cabinet: null, cabinetChannel: null, collector: null,
- expectedBarcode: null,
+ expectedBarcode: null, preservedFields: [],
temperature1: '', temperature2: '', temperature3: '', positive1: '', positive2: '', negative1: '', negative2: '',
customChannels: Object.fromEntries(customChannelColumns.value.map(column => [column.key, ''])),
}
@@ -127,7 +121,7 @@
function createThresholdRow(type = ''): ThresholdRow {
return {
key: thresholdKey++, selected: false, type, min: '', max: '',
- unit: thresholdTypes.find(item => item.value === type)?.unit || 'V',
+ unit: thresholdTypes.find(item => item.value === type)?.unit || 'V', severity: 'WARNING',
}
}
@@ -196,21 +190,6 @@
batteries.value = batteries.value.filter(item => !item.selected)
}
-function getSensorSelections(item: BatteryRow) {
- return [
- ...fixedSensorFields.map(field => ({ id: field, value: item[field] })),
- ...customChannelColumns.value.map(column => ({ id: `custom:${column.key}`, value: item.customChannels[column.key] || '' })),
- ]
-}
-
-function clearSensorSelection(item: BatteryRow, fieldId: string) {
- if (fieldId.startsWith('custom:')) {
- item.customChannels[fieldId.slice(7)] = ''
- return
- }
- item[fieldId as FixedSensorField] = ''
-}
-
function channelsForCabinet(cabinetId: number | null) {
if (!cabinetId) return []
return (configurationOptions.value?.channels || []).filter(channel => channel.cabinetId === cabinetId)
@@ -220,69 +199,12 @@
return batteries.value.some(other => other.key !== item.key && other.cabinetChannel === channelId)
}
-function isSensorChannelUsed(item: BatteryRow, fieldId: string, channel: string) {
- if (!item.collector) return false
- return batteries.value.some(other => {
- if (other.key !== item.key && other.collector !== item.collector) return false
- return getSensorSelections(other).some(selection => {
- if (other.key === item.key && selection.id === fieldId) return false
- return selection.value === channel
- })
- })
-}
-
function handleCabinetChange(item: BatteryRow) {
item.cabinetChannel = null
}
-function handleCollectorChange(item: BatteryRow) {
- if (!item.collector) {
- getSensorSelections(item).forEach(selection => clearSensorSelection(item, selection.id))
- return
- }
- const occupiedChannels = new Set(
- batteries.value
- .filter(other => other.key !== item.key && other.collector === item.collector)
- .flatMap(other => getSensorSelections(other).map(selection => selection.value).filter(Boolean)),
- )
- const currentChannels = new Set<string>()
- let clearedCount = 0
- getSensorSelections(item).forEach(selection => {
- if (!selection.value) return
- if (occupiedChannels.has(selection.value) || currentChannels.has(selection.value)) {
- clearSensorSelection(item, selection.id)
- clearedCount += 1
- return
- }
- currentChannels.add(selection.value)
- })
- if (clearedCount) ElMessage.warning(`已清空 ${clearedCount} 个重复通道,请重新选择`)
-}
-
-async function addChannelField() {
- try {
- const result = await ElMessageBox.prompt('输入字段名称后,将在表格最后新增一个可选择采集器通道的列。', '添加采集器字段', {
- confirmButtonText: '添加',
- cancelButtonText: '取消',
- inputPlaceholder: '例如:壳体温度通道',
- inputValidator: (value: string) => {
- const label = value.trim()
- if (!label) return '请输入字段名称'
- if (label.length > 16) return '字段名称不能超过 16 个字'
- const normalizedLabel = label.toLocaleLowerCase()
- const labelExists = [...reservedChannelLabels, ...customChannelColumns.value.map(column => column.label)]
- .some(item => item.toLocaleLowerCase() === normalizedLabel)
- return labelExists ? '字段名称已存在' : true
- },
- })
- const label = result.value.trim()
- const key = `custom-channel-${customChannelKey++}`
- customChannelColumns.value.push({ key, label, fieldName: `custom:${label}` })
- batteries.value.forEach(item => { item.customChannels[key] = '' })
- ElMessage.success(`已添加“${label}”通道列`)
- } catch {
- // 用户取消输入时保持当前配置。
- }
+function addChannelField() {
+ ElMessage.info('采集器通道结构待现场验证')
}
function applyOptions(options: TestConfigurationOptions) {
@@ -314,17 +236,6 @@
monitorTimeoutMinutes.value = detail.monitorTimeoutMinutes || 30
preservedPlanSteps.value = detail.planSteps || []
- const fixedNames = new Set(Object.values(fixedFieldNames))
- const customFieldNames = new Set<string>()
- detail.batteries.forEach(battery => battery.fields.forEach(field => {
- if (!fixedNames.has(field.fieldName)) customFieldNames.add(field.fieldName)
- }))
- customChannelColumns.value = [...customFieldNames].map(fieldName => ({
- key: `custom-channel-${customChannelKey++}`,
- label: fieldName.startsWith('custom:') ? fieldName.slice(7) : fieldName,
- fieldName,
- }))
-
batteries.value = detail.batteries.map(battery => {
const row = createBatteryRow(battery.batteryNo, battery.groupId)
const channel = configurationOptions.value?.channels.find(item => item.channelId === battery.binding.channelId)
@@ -332,16 +243,14 @@
row.cabinetChannel = battery.binding.channelId
row.collector = battery.collectorId
row.expectedBarcode = battery.binding.expectedBarcode
- const values = new Map(battery.fields.map(field => [field.fieldName, field.fieldValue]))
- fixedSensorFields.forEach(field => { row[field] = values.get(fixedFieldNames[field]) || '' })
- customChannelColumns.value.forEach(column => { row.customChannels[column.key] = values.get(column.fieldName) || '' })
+ row.preservedFields = battery.fields
return row
})
thresholds.value = detail.thresholds.map(item => ({
key: thresholdKey++, selected: false, type: item.metricCode,
min: item.minValue === null ? '' : String(item.minValue),
max: item.maxValue === null ? '' : String(item.maxValue),
- unit: item.unit,
+ unit: item.unit, severity: item.severity || 'WARNING',
}))
}
@@ -393,21 +302,12 @@
const value = batteries.value[index][field]
if (value === null || value === undefined || !String(value).trim()) return `第 ${index + 1} 行请选择${label}`
}
- if (!batteries.value[index].collector && getSensorSelections(batteries.value[index]).some(item => item.value)) {
- return `第 ${index + 1} 行配置采集器通道前请先选择采集器`
- }
}
const groupIds = new Set(batteries.value.map(item => item.groupId))
if (groupIds.size !== 1) return '同一测试只能选择一个电池组'
const cabinetChannels = batteries.value.map(item => item.cabinetChannel)
if (new Set(cabinetChannels).size !== cabinetChannels.length) return '同一检测柜通道不可重复绑定'
-
- const collectorChannels = batteries.value.flatMap(item => [
- ...fixedSensorFields.map(field => item[field]),
- ...customChannelColumns.value.map(column => item.customChannels[column.key]),
- ].filter(Boolean).map(channel => `${item.collector}/${channel}`))
- if (new Set(collectorChannels).size !== collectorChannels.length) return '同一采集器的采集通道不可重复'
if (!thresholds.value.length) return '至少需要配置一项预警阈值'
for (let index = 0; index < thresholds.value.length; index += 1) {
@@ -419,13 +319,7 @@
}
function buildBatteryFields(item: BatteryRow) {
- const fixedFields = fixedSensorFields
- .filter(field => item[field])
- .map(field => ({ fieldName: fixedFieldNames[field], fieldValue: item[field] }))
- const customFields = customChannelColumns.value
- .filter(column => item.customChannels[column.key])
- .map(column => ({ fieldName: column.fieldName, fieldValue: item.customChannels[column.key] }))
- return [...fixedFields, ...customFields]
+ return item.preservedFields
}
async function submit() {
@@ -459,7 +353,7 @@
minValue: item.min === '' ? null : Number(item.min),
maxValue: item.max === '' ? null : Number(item.max),
unit: item.unit,
- severity: 'WARNING' as const,
+ severity: item.severity,
})),
}
if (testId.value) await updateTest({ ...payload, testId: testId.value })
@@ -506,7 +400,7 @@
</header>
<div class="section-actions">
<div><button class="primary-button" type="button" @click="openBatteryDialog"><el-icon><Plus /></el-icon>添加电池</button><button class="secondary-button" type="button" @click="addChannelField"><el-icon><Plus /></el-icon>添加项</button><button class="secondary-button danger" type="button" @click="removeBatteries"><el-icon><Delete /></el-icon>删除所选</button></div>
- <span>至少配置一块电池 · 同一采集器通道不可重复</span>
+ <span>至少配置一块电池 · 采集器通道结构待现场验证</span>
</div>
<div class="config-table-wrap">
<table class="config-table battery-table" :style="{ minWidth: `${1700 + customChannelColumns.length * 150}px` }">
@@ -521,12 +415,12 @@
<td><el-input v-model="item.batteryNo" disabled placeholder="电池号" /></td>
<td><el-select v-model="item.cabinet" placeholder="选择" @change="handleCabinetChange(item)"><el-option v-for="option in cabinetOptions" :key="option.id" :label="option.label" :value="option.id" /></el-select></td>
<td><el-select v-model="item.cabinetChannel" clearable :disabled="!item.cabinet" :placeholder="item.cabinet ? '选择' : '请先选择检测柜'"><el-option v-for="option in channelsForCabinet(item.cabinet)" :key="option.channelId" :label="isCabinetChannelUsed(item, option.channelId) ? `${option.displayNo || `CH-${option.chlid}`}(已占用)` : option.displayNo || `CH-${option.chlid}`" :value="option.channelId" :disabled="isCabinetChannelUsed(item, option.channelId)" /></el-select></td>
- <td><el-select v-model="item.collector" clearable placeholder="选择(选填)" @change="handleCollectorChange(item)"><el-option v-for="option in collectorOptions" :key="option.id" :label="option.label" :value="option.id" /></el-select></td>
+ <td><el-select v-model="item.collector" clearable placeholder="选择(选填)"><el-option v-for="option in collectorOptions" :key="option.id" :label="option.label" :value="option.id" /></el-select></td>
<td v-for="field in fixedSensorFields" :key="field">
- <el-select v-model="item[field]" clearable :disabled="!item.collector" :placeholder="item.collector ? '选择' : '请先选择采集器'"><el-option v-for="option in sensorChannels" :key="option" :label="isSensorChannelUsed(item, field, option) ? `${option}(已占用)` : option" :value="option" :disabled="isSensorChannelUsed(item, field, option)" /></el-select>
+ <el-select v-model="item[field]" disabled placeholder="待现场验证" />
</td>
<td v-for="column in customChannelColumns" :key="column.key">
- <el-select v-model="item.customChannels[column.key]" clearable :disabled="!item.collector" :placeholder="item.collector ? '选择' : '请先选择采集器'"><el-option v-for="option in sensorChannels" :key="option" :label="isSensorChannelUsed(item, `custom:${column.key}`, option) ? `${option}(已占用)` : option" :value="option" :disabled="isSensorChannelUsed(item, `custom:${column.key}`, option)" /></el-select>
+ <el-select v-model="item.customChannels[column.key]" disabled placeholder="待现场验证" />
</td>
</tr>
<tr v-if="!batteries.length"><td :colspan="12 + customChannelColumns.length" class="empty-row">尚未配置电池,请点击“添加电池”</td></tr>
--
Gitblit v1.7.1