| | |
| | | const templateSaving = ref(false) |
| | | const selectedFieldIds = ref<number[]>([]) |
| | | const loadedTemplateFieldIds = ref<number[]>([]) |
| | | const currentTemplateName = ref('') |
| | | let batteryKey = 1 |
| | | |
| | | const editingId = computed(() => Number(route.params.id) || null) |
| | |
| | | |
| | | async function applyTemplate(templateId: number) { |
| | | if (!templateId) { |
| | | currentTemplateName.value = '' |
| | | selectedFieldIds.value = [] |
| | | loadedTemplateFieldIds.value = [] |
| | | form.customFields = [] |
| | | return |
| | | } |
| | | try { |
| | | currentTemplateName.value = templateOptions.value.find(item => item.id === templateId)?.name || '' |
| | | const template = await getBatteryGroupTemplate(templateId) |
| | | currentTemplateName.value = template.name |
| | | selectedFieldIds.value = [...template.fieldIds] |
| | | loadedTemplateFieldIds.value = [...template.fieldIds] |
| | | syncSelectedFields() |
| | |
| | | if (!editingId.value) return |
| | | const target = await getBatteryGroupDetail(editingId.value) |
| | | const templateId = target.templateFields[0]?.templateId || 0 |
| | | currentTemplateName.value = templateOptions.value.find(item => item.id === templateId)?.name || '' |
| | | const templateFields = target.templateFields.map(field => ({ |
| | | key: `persisted-field-${field.batteryGroupFieldId}`, |
| | | fieldId: field.batteryGroupFieldId, |
| | |
| | | form.batteries.splice(index, 1) |
| | | } |
| | | |
| | | function templateName(templateId: number) { |
| | | return templateOptions.value.find(item => item.id === templateId)?.name || '' |
| | | } |
| | | |
| | | async function saveTemplate() { |
| | | if (!form.templateId) { |
| | | ElMessage.warning('自定义字段请使用“另存模板”') |
| | |
| | | ElMessage.warning('请至少选择一个模板字段') |
| | | return |
| | | } |
| | | const name = currentTemplateName.value.trim() |
| | | if (!name) { |
| | | ElMessage.warning('模板名称不能为空') |
| | | return |
| | | } |
| | | templateSaving.value = true |
| | | try { |
| | | await updateBatteryGroupTemplate(form.templateId, templateName(form.templateId), selectedFieldIds.value) |
| | | await updateBatteryGroupTemplate(form.templateId, name, selectedFieldIds.value) |
| | | currentTemplateName.value = name |
| | | const option = templateOptions.value.find(item => item.id === form.templateId) |
| | | if (option) option.name = name |
| | | loadedTemplateFieldIds.value = [...selectedFieldIds.value] |
| | | ElMessage.success(`模板“${templateName(form.templateId)}”已保存`) |
| | | ElMessage.success(`模板“${name}”已保存`) |
| | | } catch (error) { |
| | | ElMessage.error(error instanceof Error ? error.message : '保存模板失败') |
| | | } finally { |
| | |
| | | const created = templateOptions.value.find(item => item.name === name) |
| | | if (!created) throw new Error('模板已保存,但未能重新加载') |
| | | form.templateId = created.id |
| | | currentTemplateName.value = name |
| | | loadedTemplateFieldIds.value = [...selectedFieldIds.value] |
| | | ElMessage.success(`已另存为“${name}”`) |
| | | } catch (error) { |
| | |
| | | |
| | | <aside class="template-panel" :aria-hidden="!templatePanelOpen"> |
| | | <header><div><strong>模板字段</strong><span>TEMPLATE FIELDS</span></div><button type="button" aria-label="关闭模板编辑" title="关闭" @click="templatePanelOpen = false"><el-icon><Close /></el-icon></button></header> |
| | | <label class="template-select"><span>当前模板</span><el-select v-model="form.templateId" @change="applyTemplate"><el-option label="自定义" :value="0" /><el-option v-for="item in templateOptions" :key="item.id" :label="item.name" :value="item.id" /></el-select></label> |
| | | <div class="template-meta"> |
| | | <label class="template-select"><span>当前模板</span><el-select v-model="form.templateId" @change="applyTemplate"><el-option label="自定义" :value="0" /><el-option v-for="item in templateOptions" :key="item.id" :label="item.name" :value="item.id" /></el-select></label> |
| | | <label v-if="form.templateId" class="template-name"><span>模板名称</span><el-input v-model="currentTemplateName" maxlength="100" placeholder="输入模板名称" /></label> |
| | | </div> |
| | | <div class="field-checkbox-list"> |
| | | <el-checkbox-group v-if="templateFieldOptions.length" v-model="selectedFieldIds" class="field-checkbox-grid" @change="syncSelectedFields"> |
| | | <el-checkbox v-for="field in templateFieldOptions" :key="field.id" :value="field.id" :disabled="field.status === '禁用'" :title="`${field.name}(${field.type},${field.status})`">{{ field.name }}</el-checkbox> |
| | |
| | | .template-panel header strong { color: var(--ink); font-size: 15px; } |
| | | .template-panel header span { color: #82919d; font-size: 9px; } |
| | | .template-panel header > button { color: #52606d; } |
| | | .template-select { display: grid; grid-template-columns: 68px minmax(0, 1fr); align-items: center; gap: 8px; padding: 16px; border-bottom: 1px solid var(--line); } |
| | | .template-meta { border-bottom: 1px solid var(--line); } |
| | | .template-select, .template-name { display: grid; grid-template-columns: 68px minmax(0, 1fr); align-items: center; gap: 8px; padding: 16px 16px 0; } |
| | | .template-name { padding-bottom: 16px; } |
| | | .field-checkbox-list { min-height: 0; padding: 18px 16px; overflow-y: auto; overscroll-behavior: contain; } |
| | | .field-checkbox-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 15px 10px; } |
| | | .field-checkbox-grid :deep(.el-checkbox) { min-width: 0; margin: 0; overflow: hidden; } |