Newer
Older
carbon-metering-front / src / views / data / electricity / components / busbarAdd.vue
<!--
  Description: 配电网母线参数新增或修改
  Author: 李亚光
  Date: 2023-04-21
 -->
<script lang="ts" setup name="deviceAdd">
import type { FormRules } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import { electricityNode, electricityNodeAdd, electricityNodeUpdate } from '@/api/api/index'
import { getDictByCode } from '@/api/system/dict'
const props = defineProps({
  id: {
    type: String,
    required: true,
  },
})
const emits = defineEmits(['refresh'])
const dataFormRef = ref()
const dialogFormVisible = ref(false) // 对话框是否显示
const dialogStatus = ref('') // 对话框类型:create,update
const isEditMode = ref(true)
const rowData = ref()
// 表单
const areaForm = ref({
  type: '', // 节点类型
  gs: '', // 节点并联电导
  bs: '', // 节点并联电纳
  area: '', // 母线断面号
  vm: '', // 节点电压初始幅值
  va: '', // 节点电压初始相位角
  zone: '', // 母线省损耗区域
  vmax: '', // 节点最大电压
  vmin: '', // 节点最小电压
  pd: '', // 负荷有功功率
  qd: '', // 负荷无功功率
  id: '',
  electricityId: '',
  nodeName: '',
  lng: '',
  lat: '',
  busId: '',
})
const locationData = ref<number[]>([]) // 经纬度 - 展示用
const locationDataStr = computed(() => locationData.value.join())
watch(() => locationData.value, (newVal: number[]) => {
  if (newVal.length) {
    areaForm.value.lng = newVal[0].toString()
    areaForm.value.lat = newVal[1].toString()
  }
}, { deep: true })
const textMap: { [key: string]: string } = {
  update: '编辑',
  create: '新增',
  detail: '详情',
} // 表头显示标题
const btnLoading = ref(false) // 保存按钮的加载中状态
// 获取所有节点
const NodeListAll = ref()
const fetchDataList = () => {
  electricityNode(props.id).then((res) => {
    NodeListAll.value = res.data.map(item => item.busId.toString())
  })
}
// 节点编号验证规则(不能重复)
const validateBusId = (rule: any, value: any, callback: any) => {
  // 修改的验证
  if (dialogStatus.value === 'update') {
    if (!(NodeListAll.value.filter(item => item !== rowData.value.busId.toString()).includes(value.toString()))) {
      callback()
    }
    else {
      callback(new Error('验证失败'))
    }
  }
  else {
    // 新增的验证
    if (!NodeListAll.value.includes(value.toString())) {
      callback()
    }
    else {
      callback(new Error('验证失败'))
    }
  }
}
const rules: FormRules = {
  type: [{ required: true, message: '请选择节点类型', trigger: ['blur', 'change'] }],
  busId: [{ required: true, message: '节点编号重复或为空', trigger: 'blur', validator: validateBusId }],
  gs: [{ required: true, message: '请输入节点并联电导', trigger: ['blur', 'change'] }],
  bs: [{ required: true, message: '请输入节点并联电纳', trigger: ['blur', 'change'] }],
  area: [{ required: true, message: '请输入母线断面号', trigger: ['blur', 'change'] }],
  vm: [{ required: true, message: '请输入节点电压初始幅值', trigger: ['blur', 'change'] }],
  va: [{ required: true, message: '请输入节点电压初始相位角', trigger: ['blur', 'change'] }],
  zone: [{ required: true, message: '请输入母线省损耗区域', trigger: ['blur', 'change'] }],
  vmax: [{ required: true, message: '请输入节点最大电压', trigger: ['blur', 'change'] }],
  vmin: [{ required: true, message: '请输入节点最小电压', trigger: ['blur', 'change'] }],
  pd: [{ required: true, message: '请输入负荷有功功率', trigger: ['blur', 'change'] }],
  qd: [{ required: true, message: '请输入负荷无功功率', trigger: ['blur', 'change'] }],
  lng: [{ required: true, message: '请选择节点经纬度坐标', trigger: ['blur', 'change'] }],
  lat: [{ required: true, message: '请输入节点纬度', trigger: ['blur', 'change'] }],
  nodeName: [{ required: true, message: '请输入节点名称', trigger: ['blur', 'change'] }],
} // 前端校验规则
// 重置表单
const resetForm = () => {
  areaForm.value = {
    type: '', // 节点类型
    gs: '', // 节点并联电导
    bs: '', // 节点并联电纳
    area: '', // 母线断面号
    vm: '', // 节点电压初始幅值
    va: '', // 节点电压初始相位角
    zone: '', // 母线省损耗区域
    vmax: '', // 节点最大电压
    vmin: '', // 节点最小电压
    pd: '', // 负荷有功功率
    qd: '', // 负荷无功功率
    id: '',
    electricityId: '',
    nodeName: '',
    lng: '',
    lat: '',
    busId: '',
  }
  locationData.value = []
}
const nodeTypeList = ref([])
// 获取设备类型列表
const fetchNodeType = () => {
  getDictByCode('node_type').then((res) => {
    nodeTypeList.value = res.data
  })
}
fetchNodeType()
// 初始化对话框
const initDialog = (dialogStatusValue: string, row: any, id: string) => {
  fetchDataList()
  dialogStatus.value = dialogStatusValue
  dialogFormVisible.value = true
  btnLoading.value = false
  if (dialogStatus.value === 'create') { // 如果是新增,清除验证
    resetForm()
    isEditMode.value = false
    nextTick(() => {
      dataFormRef.value.clearValidate()
    })
    areaForm.value.electricityId = id
    isEditMode.value = true
  }
  else if (dialogStatus.value === 'update' || dialogStatus.value === 'detail') { // 如果是修改,将row中数据填写到输入框中
    areaForm.value = row
    if (row.lng && row.lat) {
      locationData.value = [Number(row.lng), Number(row.lat)]
    }
    rowData.value = JSON.parse(JSON.stringify(row))
    areaForm.value.type = row.type.toString()
    isEditMode.value = true
  }
  if (dialogStatus.value === 'detail') {
    isEditMode.value = false
  }
}
defineExpose({
  initDialog,
})

// 新增数据
const createData = () => {
  dataFormRef.value.validate((valid: any) => {
    if (valid) {
      btnLoading.value = true
      electricityNodeAdd(areaForm.value).then((response) => {
        if (response.code === 200) {
          btnLoading.value = false
          // 通知父组件刷新状态
          setTimeout(() => {
            emits('refresh')
          })
          ElMessage({
            message: '添加成功',
            type: 'success',
          })
          dialogFormVisible.value = false
        }
      }).catch((_) => { // 异常情况,loading置为false
        btnLoading.value = false
      })
    }
  })
}

// 修改数据
const updateData = () => {
  dataFormRef.value.validate((valid: any) => {
    if (valid) {
      btnLoading.value = true
      electricityNodeUpdate(areaForm.value).then((response) => {
        if (response.code === 200) {
          ElMessage({
            message: '修改成功',
            type: 'success',
          })
          dataFormRef.value.clearValidate()
          setTimeout(() => {
            emits('refresh')
          })
          dialogFormVisible.value = false
        }
      }).catch((_) => { // 异常情况,loading置为false
        btnLoading.value = false
      })
    }
  })
}

// 保存数据
const saveData = () => {
  if (dialogStatus.value === 'update') {
    updateData()
  }
  else if (dialogStatus.value === 'create') {
    createData()
  }
}
const cancel = () => {
  dialogFormVisible.value = false
}
const selectRef = ref()
// 选择经纬度
const selectLocation = () => {
  selectRef.value.initDialog(locationData.value)
}
// 确定经纬度
const confirm = (data: number[]) => {
  locationData.value = data
}
</script>

<template>
  <el-dialog v-model="dialogFormVisible" :title="textMap[dialogStatus]" append-to-body>
    <select-location-map ref="selectRef" @confirm="confirm" />
    <el-form ref="dataFormRef" :class="[dialogStatus === 'detail' ? 'isDetail' : '']" :rules="rules" :model="areaForm" label-position="right" label-width="160px" :disabled="!isEditMode">
      <el-row :gutter="24">
        <el-col :span="12">
          <el-form-item label="节点名称:" prop="nodeName">
            <el-input v-model="areaForm.nodeName" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="节点编号:" prop="busId">
            <el-input v-model="areaForm.busId" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="24">
        <el-col :span="12">
          <el-form-item label="节点类型:" prop="type">
            <el-select v-model="areaForm.type" class="m-2" style="width: 100%;">
              <el-option v-for="item in nodeTypeList" :key="item.id" :label="item.name" :value="item.value" />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="节点经纬度:" prop="lng">
            <el-input v-model="locationDataStr" @focus="selectLocation" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="24">
        <el-col :span="12">
          <el-form-item label="节点并联电导:" prop="gs">
            <el-input v-model="areaForm.gs" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="节点并联电纳:" prop="bs">
            <el-input v-model="areaForm.bs" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="24">
        <el-col :span="12">
          <el-form-item label="母线断面号:" prop="area">
            <el-input v-model="areaForm.area" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="节点电压初始幅值:" prop="vm">
            <el-input v-model="areaForm.vm" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="24">
        <el-col :span="12">
          <el-form-item label="节点电压初始相位角:" prop="va">
            <el-input v-model="areaForm.va" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="母线省损耗区域:" prop="zone">
            <el-input v-model="areaForm.zone" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="24">
        <el-col :span="12">
          <el-form-item label="节点最大电压:" prop="vmax">
            <el-input v-model="areaForm.vmax" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="节点最小电压:" prop="vmin">
            <el-input v-model="areaForm.vmin" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="24">
        <el-col :span="12">
          <el-form-item label="负荷有功功率:" prop="pd">
            <el-input v-model="areaForm.pd" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="负荷无功功率:" prop="qd">
            <el-input v-model="areaForm.qd" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button v-if="dialogStatus !== 'detail'" :loading="btnLoading" type="primary" @click="saveData">
          保存
        </el-button>
        <el-button @click="cancel">
          {{ dialogStatus === 'detail' ? '确认' : '取消' }}
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style lang="scss" scoped>
.el-dialog {
  width: 700px;
}

.el-select {
  width: 100%;
}

.isDetail {
  ::v-deep {
    .el-form-item.is-required:not(.is-no-asterisk) .el-form-item__label-wrap > .el-form-item__label::before,
    .el-form-item.is-required:not(.is-no-asterisk) > .el-form-item__label::before {
      display: none;
    }
  }
}
</style>