<script lang="ts" setup name="EditLine"> import type { Ref } from 'vue' import { nextTick, reactive } from 'vue' import { ElMessage, ElMessageBox } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus' import type { LineListInfo, PointInfo } from './line-interface' import { isInRange, isInRangeNum, isIp, isPort } from '@/utils/validate' import { HCPreset, ToPosition, getLineList } from '@/api/ptz/line' const emits = defineEmits(['closeRefresh']) // 对话框类型:create,update const dialogStatus = ref('create') const dialogVisible = ref(false) const disabledBtn = ref(true) const presetName = ref('') // 显示标题 const textMap: { [key: string]: string } = { detail: '详情', update: '编辑', create: '新增', insert: '插入', } // 表单数据对象 const formData: Ref<PointInfo> = ref({ deviceIp: '', command: '', presetIndex: '', cruiseRoute: '', presetName: '', cruiseName: '', direction: '', pitch: '', speed: '', stopTime: '', alarmValue: '', }) // 保存按钮加载状态 const btnLoading = ref(false) // ---------------表单提交-------------------------------- const isInRangeV = function (min: number, max: number) { return function (rule: any, value: any, callback: any) { if (value === '' || !isInRange(value, min, max)) { callback(new Error(`请输入${min.toString()}-${max.toString()}整数`)) } else { callback() } callback() } } const isInRangeNumV = function (min: number, max: number, length: number) { return function (rule: any, value: any, callback: any) { if (isNaN(value) || value === '') { callback(new Error(`请输入${min.toString()}-${max.toString()}范围${length}位小数`)) } else if (isInRangeNum(Number(value), min, max)) { if (value.toString().includes('.') && value.toString().split('.')[1].length > length) { callback(new Error(`请输入${min.toString()}-${max.toString()}范围${length}位小数`)) } callback() } else { callback(new Error(`请输入${min.toString()}-${max.toString()}范围${length}位小数`)) } callback() } } // 表单对象 const dataFormRef = ref<FormInstance>() // 校验规则 const rules = reactive<FormRules>({ presetName: [{ required: true, message: '预置点名不能为空', trigger: ['blur', 'change'] }], cruiseRoute: [{ required: true, message: '巡航路径不能为空', trigger: ['blur', 'change'] }], direction: [{ required: true, message: '请输入合法方向角(0~360整数/一位小数)', trigger: ['blur', 'change'], validator: isInRangeNumV(0, 360, 1) }], pitch: [{ required: true, message: '请输入合法方向角(-90~90整数/一位小数)', trigger: ['blur', 'change'], validator: isInRangeNumV(-90, 90, 1) }], speed: [{ type: 'number', required: true, message: '请输入合法巡航速度(1~63整数)', trigger: ['blur', 'change'], validator: isInRangeV(1, 63) }], stopTime: [{ type: 'number', required: true, message: '请输入合法停留时间(0~255整数)', trigger: ['blur', 'change'], validator: isInRangeV(0, 255) }], alarmValue: [{ type: 'number', required: true, message: '请输入合法报警阈值(0~10000整数)', trigger: ['blur', 'change'], validator: isInRangeV(0, 10000) }], }) const lineList: Ref<LineListInfo[]> = ref([]) function getLine(id: string) { getLineList('', id).then((res) => { lineList.value = res.data }) } // 获取场站列表 const stationList: Ref<StationListInfo[]> = ref([]) function fetchStationList() { getStationList().then((res) => { stationList.value = res.data }) } // 表单提交 function submitForm() { if (dataFormRef) { dataFormRef.value?.validate((valid: boolean) => { if (valid) { ElMessageBox.confirm( '确认设备已定位至输入视角?', '确认保存', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', }, ).then(() => { if (dialogStatus.value === 'create') { createData() } else if (dialogStatus.value === 'update') { updateData() } else if (dialogStatus.value === 'insert') { insertData() } }) } }) } } // 定位视图 function posView() { // console.log(formData.value.direction,formData.value.pitch) if (formData.value.direction !== '' && formData.value.pitch !== '') { setTimeout(() => { disabledBtn.value = false const params = { deviceIp: formData.value.deviceIp, horizontalAngle: formData.value.direction, verticalAngle: formData.value.pitch, } ToPosition(params).then((res) => { console.log(res) }) }, 2000) } else { ElMessage.warning('请输入合法方向角度!') } } // 新增数据 function createData() { formData.value.cruiseName = lineList.value.filter(item => item.id === formData.value.cruiseRoute)[0].lineName HCPreset(formData.value).then((res) => { ElMessage.success('新增成功') btnLoading.value = false closeRefresh() }).catch((_) => { // 异常情况,loading置为false btnLoading.value = false }) } // 更新数据 function updateData() { HCPreset(formData.value).then((res) => { ElMessage.success('修改成功') btnLoading.value = false closeRefresh() }).catch((_) => { // 异常情况,loading置为false btnLoading.value = false }) } // 更新数据 function insertData() { console.log(formData.value) HCPreset(formData.value).then((res) => { ElMessage.success('插入成功') btnLoading.value = false closeRefresh() }).catch((_) => { // 异常情况,loading置为false btnLoading.value = false }) } // 重置表单 function resetForm() { formData.value = { deviceIp: '', command: '', presetIndex: '', cruiseRoute: '', presetName: '', cruiseName: '', direction: '', pitch: '', speed: '', stopTime: '', alarmValue: '', } } // ----------初始化、关闭对话框相关----------------- function initDialog(dialogstatus: string, row: any) { disabledBtn.value = true dialogStatus.value = dialogstatus dialogVisible.value = true btnLoading.value = false resetForm() if (dialogstatus === 'create') { getLine(row.id) formData.value.command = 'presetAdd' formData.value.deviceIp = row.ip nextTick(() => { dataFormRef.value?.clearValidate() }) } else if (dialogstatus === 'update' || dialogstatus === 'detail' || dialogstatus === 'insert') { nextTick(() => { dataFormRef.value?.clearValidate() }) getLine(row.monitorId) presetName.value = row.serialName formData.value = { deviceIp: row.ip, command: dialogstatus === 'insert' ? 'presetInsert' : 'presetEdit', presetIndex: dialogstatus === 'insert' ? '' : row.serialNum, presetName: dialogstatus === 'insert' ? '' : row.serialName, cruiseRoute: row.lineNum.toString(), cruiseName: row.lineName, direction: dialogstatus === 'insert' ? '' : row.direction, pitch: dialogstatus === 'insert' ? '' : row.pitch, speed: dialogstatus === 'insert' ? '' : row.speed, stopTime: dialogstatus === 'insert' ? '' : row.stopTime, alarmValue: dialogstatus === 'insert' ? '' : row.alarmValue, } console.log(row.lineNum.toString()) console.log(typeof (formData.value.cruiseRoute)) } } // 关闭并刷新 function closeRefresh() { dialogVisible.value = false resetForm() emits('closeRefresh') } // 关闭弹窗 function dialogClose() { dialogVisible.value = false resetForm() closeRefresh() } onMounted(() => { }) // ----------------------- 以下是暴露的方法内容 ---------------------------- defineExpose({ initDialog }) </script> <template> <el-dialog v-model="dialogVisible" :title="textMap[dialogStatus]" width="50%" :before-close="dialogClose" append-to-body :open-delay="0" :close-on-click-modal="false" > <el-form ref="dataFormRef" :model="formData" :rules="rules" label-position="left" label-width="150px" class="form-container" size="default" @submit.prevent > <el-row :gutter="10"> <el-col :span="18" :offset="2" class="grid-cell"> <el-form-item label="巡航路径" prop="cruiseRoute" class="required"> <el-select v-model="formData.cruiseRoute" :disabled="dialogStatus !== 'create'" placeholder="必选" style="width: 100%;"> <el-option v-for="item in lineList" :key="item.id" :label="item.lineName" :value="item.id" /> </el-select> </el-form-item> </el-col> <el-col v-if="dialogStatus === 'insert'" :span="18" :offset="2" class="grid-cell"> <el-form-item label="* 原预置点名" class="required"> <el-input v-model="presetName" disabled type="text" placeholder="必填" /> </el-form-item> </el-col> <el-col :span="18" :offset="2" class="grid-cell"> <el-form-item label="预置点名" prop="presetName" class="required"> <el-input v-model="formData.presetName" :disabled="dialogStatus === 'detail' || dialogStatus === 'update'" type="text" placeholder="必填" /> </el-form-item> </el-col> <el-col :span="18" :offset="2" class="grid-cell"> <el-form-item label="方位角(°)" prop="direction" class="required"> <el-input v-model="formData.direction" :disabled="dialogStatus === 'detail'" type="text" placeholder="必填" @input="disabledBtn = true" /> </el-form-item> </el-col> <el-col :span="18" :offset="2" class="grid-cell"> <el-form-item label="俯仰角(°)" prop="pitch" class="required"> <el-input v-model="formData.pitch" :disabled="dialogStatus === 'detail'" type="text" placeholder="必填" @input="disabledBtn = true" /> </el-form-item> </el-col> <el-col :span="18" :offset="2" class="grid-cell"> <el-form-item label="默认巡航速度(m/s)" prop="speed" class="required"> <el-input v-model="formData.speed" :disabled="dialogStatus === 'detail'" type="text" placeholder="例如:30" /> </el-form-item> </el-col> <el-col :span="18" :offset="2" class="grid-cell"> <el-form-item label="默认停留时间(s)" prop="stopTime" class="required"> <el-input v-model="formData.stopTime" :disabled="dialogStatus === 'detail'" type="text" placeholder="例如:3" /> </el-form-item> </el-col> <el-col :span="18" :offset="2" class="grid-cell"> <el-form-item label="默认报警值(ppm·m)" prop="alarmValue" class="required"> <el-input v-model="formData.alarmValue" :disabled="dialogStatus === 'detail'" type="text" placeholder="例如:5000" /> </el-form-item> </el-col> </el-row> </el-form> <template #footer> <div v-show="dialogStatus !== 'detail'" class="dialog-footer"> <el-button :loading="btnLoading" type="primary" @click="posView"> 定位视角 </el-button> <el-button :loading="btnLoading" type="primary" :disabled="disabledBtn" @click="submitForm"> 保存 </el-button> <el-button @click="dialogClose"> 取消 </el-button> </div> </template> </el-dialog> </template> <style lang="scss" scoped> .form-container { width: 100%; .full-width-input { width: 100%; } .dict-detail { padding: 10px; .title { font-size: 16px; font-weight: bold; margin-bottom: 15px; } } } </style>