<!-- Description: 特殊报警规则-编辑新建 Author: 李亚光 Date: 2024-09-09 --> <script lang="ts" setup name="EditAlarmRuleSPecial"> import type { FormRules } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus' import { getDictByCode } from '@/api/system/dict' import { getDeviceTypeListPage } from '@/api/home/device/type' import { getAlarmLevelListPage, getAlarmTypeListPage, } from '@/api/home/rule/alarm' import { getAlarmRuleListPage } from '@/api/home/rule/alarm' import { addSpecialAlarmRule, editSpecialAlarmRule, getProductAlarmRule, } from '@/api/home/rule/special' import { getDeviceListPage } from '@/api/home/device/device' import { getProductListPage } from '@/api/home/device/product' import { useCheckList } from '@/utils/useCheckList' import indexDB from '@/utils/indexDB' import { indexDBHandler } from '@/utils/sessionData' const emits = defineEmits(['refresh']) const deviceList = ref<any[]>([]) // 设备列表 const productList = ref<any[]>([]) // 产品 const alarmRuleList = ref<any[]>([]) // 报警规则 const alarmRuleAllList = ref<any[]>([]) // 报警规则 const alarmLevelList = ref<any[]>([]) // 报警等级 const dataFormRef = ref() const dialogFormVisible = ref(false) // 对话框是否显示 const dialogStatus = ref('') // 对话框类型:create,update const dataForm = ref({ devcode: '', // 设备编号 tagNumber: '', // 位号 position: '', // 详细位置 alarmLevelId: '', // 报警等级id alarmTypeId: '', // 报警类型 alarmThreshold: '', // 报警阈值 productId: '', alarmRule: '', id: '', }) // 表单 const textMap: { [key: string]: string } = { edit: '编辑', create: '新增', detail: '', } // 表头显示标题 const rules: FormRules = { devcode: [{ required: true, message: '设备编号不能为空', trigger: ['blur', 'change'] }], } // 前端校验规则 // 重置表单 const resetForm = () => { dataForm.value = { devcode: '', // 设备编号 tagNumber: '', // 位号 position: '', // 详细位置 alarmLevelId: '', // 报警等级id alarmTypeId: '', // 报警类型 alarmThreshold: '', // 报警阈值 productId: '', alarmRule: '', id: '', } } const list = ref<any[]>([]) const columns = ref<any>([ { text: '报警规则', value: 'alarmRuleId', align: 'center', type: 'select', code: 'alarm-rule', required: true, }, { text: '报警等级', value: 'alarmLevelId', align: 'center', type: 'select', code: 'alarm-level', required: true, }, { text: '报警阈值', value: 'alarmThreshold', align: 'center', type: 'input', required: true, }, ]) // 初始化对话框 const isFirst = ref(true) const disabledBtn = ref(false) // 初始数据 const initDeviceCode = ref('') const initAlarmRule = ref<any[]>([]) const initDialog = (dialogStatusValue: string, row: any) => { dialogStatus.value = dialogStatusValue isFirst.value = true disabledBtn.value = false dialogFormVisible.value = true if (dialogStatus.value === 'create') { // 如果是新增,清除验证 resetForm() // nextTick(() => { // dataFormRef.value.clearValidate() // }) dataFormRef.value?.resetFields() list.value = [] initDeviceCode.value = '' initAlarmRule.value = [] } else if (dialogStatus.value === 'edit' || dialogStatus.value === 'detail') { // 如果是修改,将row中数据填写到输入框中 dataForm.value = { ...JSON.parse(JSON.stringify(row)), } initDeviceCode.value = dataForm.value.devcode const alarmLevelIds = dataForm.value.alarmLevelIds.split(',') const alarmRuleIds = dataForm.value.alarmRuleIds.split(',') const alarmThresholds = dataForm.value.alarmThresholds.split(',') list.value = alarmLevelIds.map((item: string, index: number) => ({ edit: dialogStatus.value === 'edit', alarmRuleId: alarmRuleIds[index], alarmThreshold: alarmThresholds[index], alarmLevelId: item, alarmTypeId: row.alarmTypeId, isConcentration: row.alarmType.includes('浓度'), })) // list.value = [ // { // edit: dialogStatus.value === 'edit', // alarmRuleId: row.alarmRuleId, // alarmLevelId: row.alarmLevelId, // alarmThreshold: row.alarmThreshold, // alarmTypeId: row.alarmTypeId, // isConcentration: row.alarmType.includes('浓度'), // }, // ] initAlarmRule.value = JSON.parse(JSON.stringify(list.value)) } setTimeout(() => { isFirst.value = false }) } watch(() => dataForm.value.devcode, (newVal) => { if (newVal) { // console.log(newVal, isFirst.value, '设备编号') if (!isFirst.value) { if (newVal !== initDeviceCode.value) { getProductAlarmRule({ devCode: newVal }).then((res) => { // console.log(res.data, '报警规则') list.value = res.data.map((item: any) => ({ edit: true, alarmTypeId: item.alarmTypeId, alarmThreshold: item.alarmThreshold, alarmLevelId: item.alarmLevelId, alarmRuleId: item.alarmRuleId, alarmRuleName: item.alarmRuleName, isConcentration: item.alarmTypeName.includes('浓度'), })) }) } else { list.value = JSON.parse(JSON.stringify(initAlarmRule.value)) } } } }) defineExpose({ initDialog, }) // 新增数据 const createData = (data: any) => { dataFormRef.value.validate((valid: any) => { if (valid) { // 验证数据列 if (useCheckList(list.value, columns.value, '报警规则')) { disabledBtn.value = true addSpecialAlarmRule(data) .then((response) => { if (response.code === 200) { ElMessage({ message: '添加成功', type: 'success', }) disabledBtn.value = false // 通知父组件刷新状态 dialogFormVisible.value = false setTimeout(() => { emits('refresh') }) } }) .catch((_) => { // 异常情况,loading置为false disabledBtn.value = false }) } } }) } // 修改数据 const updateData = (data: any) => { dataFormRef.value.validate((valid: any) => { if (valid) { if (useCheckList(list.value, columns.value, '报警规则')) { disabledBtn.value = true editSpecialAlarmRule(data) .then((response) => { if (response.code === 200) { ElMessage({ message: '修改成功', type: 'success', }) setTimeout(() => { emits('refresh') }) dialogFormVisible.value = false disabledBtn.value = false } }) .catch((_) => { // 异常情况,loading置为false disabledBtn.value = false }) } } }) } // 保存数据 const saveData = () => { if (!list.value.length) { ElMessage.warning('报警规则为空') return } if (list.value.filter((item: any) => item.edit).length) { ElMessage.warning('请先保存报警规则') return } const data = list.value.map((item: any) => ({ alarmLevelId: item.alarmLevelId, alarmTypeId: item.alarmTypeId, // alarmRule: item.alarmRule, alarmRuleId: item.alarmRuleId, alarmRuleName: alarmRuleList.value.filter((citem: any) => citem.id === item.alarmRuleId)[0]?.name || '', alarmThreshold: item.alarmThreshold, devcode: dataForm.value.devcode, id: dataForm.value.id, position: dataForm.value.position, tagNumber: dataForm.value.tagNumber, devTypeName: deviceList.value.filter((citem: any) => citem.value === dataForm.value.devcode)[0]?.name || '', })) // console.log(data, 'data') if (dialogStatus.value === 'edit') { updateData(data) } else if (dialogStatus.value === 'create') { createData(data) } } const cancel = () => { dialogFormVisible.value = false } // 列表添加行 const addRow = () => { list.value.push({ alarmThreshold: '', alarmLevelId: '', alarmRule: '', edit: true, }) } // 保存行 const saveRow = (scope: any) => { const row = scope.row as any if (String(row.alarmThreshold) && row.alarmLevelId) { list.value[scope.$index].edit = false } else { ElMessage.warning('请先完善当前行数据') } } // 编辑行 const editRow = (scope: any) => { list.value[scope.$index].edit = true } // 删除行 const removeRow = (scope: any) => { ElMessageBox.confirm('确定要删除该数据吗?', '确认操作', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', }).then(() => { list.value = list.value.filter((item, index) => index !== scope.$index) ElMessage.success('操作成功') }) } // 字典 const fetchDict = () => { // 先从缓存中获取设备列表 indexDB.getAll().then(allData => { if (allData.filter((item: any) => item.name === 'all-device-list').length) { deviceList.value = JSON.parse(allData.filter((item: any) => item.name === 'all-device-list')[0].data) } else { getDeviceListPage({ offset: 1, limit: 9999 }).then((res) => { deviceList.value = res.data.rows.map((item: any) => ({ name: item.typeName, id: item.id, value: item.devcode, productId: item.productId, position: item.position, tagNumber: item.tagNumber, deviceType: item.deviceType, })).filter((item: any) => item.productId && item.value) indexDBHandler('all-device-list', JSON.stringify(deviceList.value)) }) } }) // 产品 getProductListPage({ limit: 9999, offset: 1 }).then((res) => { productList.value = res.data.rows.map((item: any) => ({ name: `${item.productName}-${item.deviceModel}/${item.manufacturerName}`, value: item.id, id: item.id, })) }) // 报警规则 getAlarmRuleListPage({ limit: 9999, offset: 1 }).then((res) => { alarmRuleAllList.value = res.data.rows alarmRuleList.value = res.data.rows.map((item: any) => ({ name: item.alarmName, id: item.id, value: item.id, alarmTypeId: item.alarmTypeId, })) }) // 报警等级 getAlarmLevelListPage({ limit: 9999, offset: 1 }).then((res) => { alarmLevelList.value = res.data.rows.map((item: any) => ({ name: item.alarmLevel, id: item.id, value: item.id, })) }) } fetchDict() // 监听设备编号,自动填充产品,安装位号,详细地址 watch(() => dataForm.value.devcode, (newVal) => { if (newVal) { const current = deviceList.value.filter((item: any) => item.value === dataForm.value.devcode) if (current.length) { dataForm.value.productId = current[0].productId dataForm.value.tagNumber = current[0].tagNumber dataForm.value.position = current[0].position alarmRuleList.value = alarmRuleAllList.value.filter((item: any) => item.productId === dataForm.value.productId) .map((item: any) => ({ name: item.alarmName, id: item.id, typeId: item.alarmTypeId })) // console.log(alarmRuleAllList.value.filter((item: any) => item.productId === dataForm.value.productId)) // console.log(alarmRuleList.value, 'alarmRuleList.value') // 根据设备类型寻找报警类型 // getAlarmTypeListPage({ limit: 9999, offset: 1 }).then((res) => { // alarmRuleList.value = res.data.rows.filter((item: any) => item.deviceTypeName.includes(current[0].name)) // .map((item: any) => ({ // name: item.alarmType, // id: item.id, // value: item.id, // })) // }) return } if (isFirst.value) { return } alarmRuleList.value = [] list.value = [] } }, { deep: true, immediate: true, }) // 改变报警类型 const changeAlarmType = (value: string, index: number) => { const alarmTypeName = alarmRuleList.value.filter(item => item.id === value)[0]?.name || '' if (alarmTypeName.includes('浓度')) { list.value[index].isConcentration = true } else { list.value[index].isConcentration = false } } const computeOptions = (val: any) => { return val.map((item: any) => ({ label: `${item.value}-${item.name}`, value: item.value })) } const computeTypeName = computed(() => { return productList.value.filter((item) => item.id === dataForm.value.productId)[0]?.name || '' }) </script> <template> <el-dialog v-model="dialogFormVisible" :title="`${textMap[dialogStatus]}特殊报警规则`" append-to-body width="900px"> <el-form ref="dataFormRef" :rules="rules" :model="dataForm" label-position="right" :disabled="dialogStatus === 'detail'" label-width="110px"> <el-row :gutter="24"> <el-col :span="12"> <el-form-item label="设备编号" prop="devcode"> <!-- <el-select v-model.trim="dataForm.devcode" placeholder="设备编号" style="width: 100%;" clearable filterable> <el-option v-for="item in deviceList" :key="item.id" :label="`${item.name}-${item.value}`" :value="item.value" /> </el-select> --> <el-select-v2 v-model="dataForm.devcode" :options="computeOptions(deviceList)" style="width: 100%;" clearable filterable> </el-select-v2> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="产品" prop="productId"> <el-select v-model.trim="dataForm.productId" placeholder="产品" style="width: 100%;" clearable filterable disabled> <el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.value" /> </el-select> </el-form-item> </el-col> </el-row> <el-row :gutter="24"> <el-col :span="12"> <el-form-item label="安装位号" prop="tagNumber"> <el-input v-model.trim="dataForm.tagNumber" type="text" placeholder="安装位号" style="width: 100%;" disabled clearable /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="详细地址" prop="position"> <el-input v-model.trim="dataForm.position" type="text" placeholder="详细地址" style="width: 100%;" disabled clearable /> </el-form-item> </el-col> </el-row> <el-row :gutter="24"> <!-- <el-col :span="24"> <el-form-item label="报警规则" prop=""> </el-form-item> </el-col> --> <el-col :span="24"> <div class="table-custom-edit" style="width: 100%;"> <table-container title="报警规则"> <template #btns-right> <!-- 操作 --> <!-- <div> <el-button v-if="dialogStatus === 'create'" type="primary" @click="addRow"> 新增 </el-button> </div> --> </template> <!-- 查询结果Table显示 --> <normal-table :data="list" :total="0" :columns="[]" :query="{}" :pagination="false"> <template #preColumns> <el-table-column label="序号" width="55" align="center"> <template #default="scope"> {{ scope.$index + 1 }} </template> </el-table-column> </template> <template #columns> <el-table-column v-for="item in columns" :key="item.text" :label="item.text" align="center"> <template #default="scope"> <!-- 报警规则 --> <template v-if="item.type === 'select' && item.code === 'alarm-rule'"> <el-select v-model.trim="scope.row[item.value]" placeholder="报警规则" style="width: 100%;" clearable filterable :disabled="!scope.row.edit" @change="() => { changeAlarmType(scope.row[item.value], scope.$index,) }"> <el-option v-for="item in alarmRuleList" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </template> <!-- 报警等级 --> <template v-if="item.type === 'select' && item.code === 'alarm-level'"> <el-select v-model.trim="scope.row[item.value]" placeholder="报警等级" style="width: 100%;" clearable filterable :disabled="!scope.row.edit"> <el-option v-for="item in alarmLevelList" :key="item.id" :label="item.name" :value="item.value" /> </el-select> </template> <!-- 报警阈值 --> <div v-if="item.type === 'input'" style="width: 100%;"> <el-input v-model.trim="scope.row[item.value]" placeholder="报警阈值" clearable type="number" style="width: 60%;" :disabled="!scope.row.edit || !scope.row.isConcentration" /> <span>{{ scope.row.isConcentration ? computeTypeName.includes('云台') ? 'PPM.M' : "%LEL" : "" }}</span> </div> </template> </el-table-column> <el-table-column v-if="dialogStatus === 'create' || dialogStatus === 'edit'" label="操作" width="140" align="center"> <template #default="scope"> <el-button v-if="scope.row.edit === true" type="primary" link size="small" @click="saveRow(scope)"> 保存 </el-button> <el-button v-if="scope.row.edit === false" type="primary" link size="small" @click="editRow(scope)"> 编辑 </el-button> <el-button v-if="scope.row.edit === true" type="danger" link size="small" @click="removeRow(scope)"> 删除 </el-button> </template> </el-table-column> </template> </normal-table> </table-container> </div> </el-col> </el-row> </el-form> <template #footer> <div v-if="dialogStatus !== 'detail'" class="dialog-footer"> <el-button :loading="disabledBtn" :disabled="disabledBtn" type="primary" @click="saveData"> 确认 </el-button> <el-button @click="cancel"> 取消 </el-button> </div> <div v-else class="dialog-footer"> <el-button :loading="disabledBtn" :disabled="disabledBtn" type="primary" @click="cancel"> 确认 </el-button> </div> </template> </el-dialog> </template> <style lang="scss" scoped> .el-dialog { width: 700px; } .el-select { width: 100%; } .table-custom-edit { ::v-deep(.table-container) { margin-top: 0; padding: 0; padding-left: 38px; } } </style>