| | |
| | | import type { CompareMetricKey, CompareTestSelection } from '@/stores/compareReports' |
| | | import { compareSelectionKey, createCompareReport, editCompareReport, getCompareReport, getCompareSources, previewCompareReport, refreshCompareSource, |
| | | type CompareCandidate, type CompareItem, type CompareSelection, type SavedCompareReport } from '@/api/compareReports' |
| | | import { listCompareFieldTemplates, createCompareFieldTemplate, type CompareFieldTemplate } from '@/api/compareReports' |
| | | import { compareMetricDefinitions as metricDefinitions, openCompareReportPrint } from '@/utils/compareReportPrint' |
| | | import { compareChartOption } from '@/utils/compareReportChart' |
| | | |
| | |
| | | const selectedBatteryTemplateFieldIds = ref<number[]>([]) |
| | | |
| | | const specialTemplateSelections = reactive<Record<string, string[]>>({}) |
| | | const persistedTemplates = ref<CompareFieldTemplate[]>([]) |
| | | const templateLoading = ref(false) |
| | | |
| | | const fieldTemplates = computed<FieldTemplate[]>(() => [ |
| | | { key: 'cycle', name: '循环寿命模板', fields: ['容量保持率', '能量效率', '循环次数', '内阻变化'] }, |
| | | { key: 'thermal', name: '热特性模板', fields: ['最高温度', '温差', '温升速率'] }, |
| | | ...Object.entries(specialTemplateSelections).map(([name, fields]) => ({ key: `saved:${name}`, name, fields })), |
| | | ...persistedTemplates.value.map(item => ({ key: `remote:${item.id}`, name: item.name, fields: item.fields.filter(field => field.category !== 'battery').map(field => field.name) })), |
| | | ]) |
| | | |
| | | const metricVisible = reactive<Record<CompareMetricKey, boolean>>({ |
| | |
| | | } finally { |
| | | candidatesLoading.value = false |
| | | } |
| | | } |
| | | |
| | | async function loadFieldTemplates() { |
| | | templateLoading.value = true |
| | | try { persistedTemplates.value = await listCompareFieldTemplates() } |
| | | catch (error) { ElMessage.error(error instanceof Error ? error.message : '字段模板加载失败') } |
| | | finally { templateLoading.value = false } |
| | | } |
| | | |
| | | function detailKey(item: SelectedTest) { |
| | |
| | | canCreate.value = Boolean(info.permissions?.some(item => item === '*:*:*' || item === 'system:compare-report:add')) |
| | | if (!canCreate.value) throw new Error('无新增对比报表权限') |
| | | await loadCandidates() |
| | | await loadFieldTemplates() |
| | | } |
| | | } catch (error) { if (!cancelled) loadError.value = error instanceof Error ? error.message : '报表加载失败' } |
| | | finally { if (!cancelled) reportLoading.value = false } |
| | |
| | | detailFields.value.forEach(ensureDetailFieldValues) |
| | | } catch (error) { previewError.value = error instanceof Error ? error.message : '曲线预览失败' } |
| | | finally { previewLoading.value = false } |
| | | } |
| | | |
| | | async function saveCurrentFieldTemplate() { |
| | | const result = await ElMessageBox.prompt('请输入模板名称', '保存对比字段模板', { inputValidator: value => value.trim() ? true : '请输入模板名称', confirmButtonText: '保存', cancelButtonText: '取消' }) |
| | | const name = result.value.trim() |
| | | const fields = [...batteryFields.value.map(name => ({ name, category: 'battery', unit: '' })), ...specialFields.value.map(name => ({ name, category: 'special', unit: '' }))] |
| | | try { await createCompareFieldTemplate(name, fields); await loadFieldTemplates(); ElMessage.success('字段模板已保存') } |
| | | catch (error) { ElMessage.error(error instanceof Error ? error.message : '模板保存失败') } |
| | | } |
| | | |
| | | function openAddTest() { |
| | |
| | | } else { |
| | | const nextFields = selectedTemplate.value.fields |
| | | specialFields.value = nextFields.filter(field => !batteryFields.value.includes(field)) |
| | | const remote = persistedTemplates.value.find(item => `remote:${item.id}` === selectedTemplateKey.value) |
| | | if (remote) batteryFields.value = remote.fields.filter(field => field.category === 'battery').map(field => field.name) |
| | | detailFields.value.forEach(ensureDetailFieldValues) |
| | | } |
| | | templateDialogVisible.value = false |
| | |
| | | <div v-else class="template-empty">暂无字段,请先到电池组字段管理中添加字段</div> |
| | | </div> |
| | | <el-radio-group v-else v-model="selectedTemplateKey" class="template-options"><el-radio v-for="item in fieldTemplates" :key="item.key" :value="item.key" border>{{ item.name }}({{ item.fields.join('、') }})</el-radio></el-radio-group> |
| | | <template #footer><div v-if="templateMode === 'battery'" class="battery-template-actions"><button class="primary-button" type="button" @click="applyFieldTemplate"><el-icon><Check /></el-icon>确认</button></div><div v-else><button class="secondary-button" type="button" @click="templateDialogVisible = false">取消</button><button class="primary-button" type="button" @click="applyFieldTemplate">应用字段</button></div></template> |
| | | <template #footer><div v-if="templateMode === 'battery'" class="battery-template-actions"><button class="secondary-button" type="button" @click="saveCurrentFieldTemplate" :disabled="templateLoading">保存为模板</button><button class="primary-button" type="button" @click="applyFieldTemplate"><el-icon><Check /></el-icon>确认</button></div><div v-else><button class="secondary-button" type="button" @click="saveCurrentFieldTemplate" :disabled="templateLoading">保存为模板</button><button class="secondary-button" type="button" @click="templateDialogVisible = false">取消</button><button class="primary-button" type="button" @click="applyFieldTemplate">应用字段</button></div></template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |