赞
踩
由于不同监测点有不同的传感器,每个传感器数据对应不同的数据表,有包含不同字段的 SQL 查询语句,因此,需要动态加载传感器并生成查询的 SQL 语句
效果图:
初始界面:
新增界面:
展示子组件 SQL 编辑器界面:
具体代码:
<template> <div class="app-container"> <!--工具栏--> <div class="head-container"> <eHeader :permission="permission" :sensorTypeCodes="dict.device_type_codes" :warnLevels="dict.warn_levels" /> <crudOperation :permission="permission" /> </div> <!--表格渲染--> <el-table ref="table" v-loading="crud.loading" :stripe="true" :data="crud.data" style="width: 100%;" @selection-change="crud.selectionChangeHandler" > <el-table-column type="selection" width="55" /> <el-table-column prop="monitorPointCode" label="监测点编号" width="160px" /> <el-table-column prop="warnLevel" label="预警级别" :formatter="warnLevelFormatter" align="center" width="100px" /> <el-table-column prop="sensorTypeCode" label="传感器类型" :formatter="deviceTypeCodeFormatter" align="center" width="100px" /> <el-table-column prop="warnName" label="报警名称" width="240px" /> <el-table-column prop="enable" label="有效" width="100px"> <template slot-scope="scope"> {{ scope.row.enable ? '有效' : '无效' }} </template> </el-table-column> <el-table-column prop="sqlStatement" label="预警SQL" /> <el-table-column prop="sensorCodeList" label="应用传感器编号" /> <!-- 编辑与删除 --> <el-table-column v-if="checkPer(['admin', 'warnSetting:edit', 'warnSetting:del'])" label="操作" width="130px" align="center" fixed="right" > <template slot-scope="scope"> <udOperation :data="scope.row" :permission="permission" /> </template> </el-table-column> </el-table> <!--分页组件--> <pagination /> <!--表单渲染--> <eForm :sensorTypeCodes="dict.device_type_codes" :warnLevels="dict.warn_levels" /> </div> </template> <script> import crudWarnSetting from '@/api/dz/warnSetting' import eHeader from './module/header' import eForm from './module/form' import CRUD, { presenter } from '@crud/crud' import crudOperation from '@crud/CRUD.operation' import pagination from '@crud/Pagination' import udOperation from '@crud/UD.operation' export default { name: 'WarnSetting', components: { eHeader, eForm, crudOperation, pagination, udOperation, }, mounted() { // console.log(this.dict.warn_levels) }, cruds() { return CRUD({ title: '报警设置信息', url: '/api/warn/setting', crudMethod: { ...crudWarnSetting }, }) }, mixins: [presenter()], // 数据字典 dicts: ['device_type_codes', 'warn_levels'], data() { return { permission: { add: ['admin', 'warnSetting:add'], edit: ['admin', 'warnSetting:edit'], del: ['admin', 'warnSetting:del'], }, } }, methods: { deviceTypeCodeFormatter(row, column) { let deviceTypeCodeName = '' this.dict.device_type_codes.forEach((item) => { if (item.value === row.sensorTypeCode) { deviceTypeCodeName = item.label } }) return deviceTypeCodeName }, warnLevelFormatter(row, column) { let warnLevelName = '' this.dict.warn_levels.forEach((item) => { if (item.value === row.warnLevel) { warnLevelName = item.label } }) return warnLevelName }, }, } </script>
<template> <div v-if="crud.props.searchToggle"> <el-input v-model="query.monitorPointCode" clearable size="small" placeholder="监测点编码搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="crud.toQuery" /> <el-select v-model="query.warnLevel" clearable size="small" placeholder="报警级别搜索" class="filter-item" style="width: 90px" @change="crud.toQuery" > <el-option v-for="item in warnLevels" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <el-select v-model="query.sensorTypeCode" clearable size="small" placeholder="传感器类型搜索" class="filter-item" style="width: 90px" @change="crud.toQuery" > <el-option v-for="item in sensorTypeCodes" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <rrOperation /> </div> </template> <script> import { header } from '@crud/crud' import rrOperation from '@crud/RR.operation' export default { components: { rrOperation }, mixins: [header()], props: { warnLevels: { type: Array, required: true, }, sensorTypeCodes: { type: Array, required: true, }, permission: { type: Object, required: true, }, }, } </script>
<template> <el-dialog append-to-body :close-on-click-modal="false" :before-close="crud.cancelCU" :visible="crud.status.cu > 0" :title="crud.status.title" width="1200px" > <el-form ref="form" :model="form" :rules="rules" size="small" label-width="120px" > <el-row> <el-col :span="8"> <el-form-item label="预警名称:" prop="warnName"> <el-input v-model="form.warnName" placeholder="请输入预警名称" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="预警级别:" prop="warnLevel" label-width="120px" > <el-select v-model="form.warnLevel" clearable size="small" placeholder="请选预警级别" class="filter-item" style="width: 238px" > <el-option v-for="item in warnLevels" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="预警是否有效:" prop="enable" label-width="120px" > <el-select v-model="form.enable" clearable size="small" placeholder="请选预警是否有效" class="filter-item" style="width: 238px" > <el-option v-for="item in enables" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="8"> <el-form-item label="绑定监测点:"> <el-button type="warning" icon="el-icon-edit" @click="showMonitorPointSelector" >选择监测点</el-button > </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="选择的监测点:"> <el-tag type="warning" >{{ selectedMonitorPointName }}</el-tag > </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="传感器类型:" prop="sensorTypeCode" label-width="120px" > <el-select v-model="form.sensorTypeCode" clearable size="small" placeholder="请选传感器类型" class="filter-item" style="width: 238px" @change="selectSensors" > <el-option v-for="item in monitorPointSensorTypeCodes" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="16"> <el-form-item label="预警SQL:" prop="sqlStatement"> <el-input type="textarea" :rows="4" v-model="form.sqlStatement" > </el-input> <el-button type="success" icon="el-icon-edit" @click="showCriteriaEditor" >SQL编辑器</el-button > </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="预警传感器:" prop="sensorCodeList"> <el-checkbox-group v-model="form.sensorCodeList"> <el-checkbox v-for="sensorCode in sensorCodes" :key="sensorCode" :label="sensorCode" ></el-checkbox> </el-checkbox-group> </el-form-item> </el-col> </el-row> </el-form> <!-- 引用组件,响应自定义事件并设置处理程序 --> <MonitorPointDialogSelector ref="monitorPointSelector" @rowSelected="setMonitorPointData" /> <CriteriaEditor ref="criteriaEditor" @confirm="setCriteriaEditorData" /> <div slot="footer" class="dialog-footer"> <el-button type="text" @click="crud.cancelCU"> 取消 </el-button> <el-button :loading="crud.status.cu === 2" type="primary" @click="crud.submitCU" > 确认 </el-button> </div> </el-dialog> </template> <script> import { getSensorInfosByMonitorPoint } from '@/api/dz/sensorInfo' import { form } from '@crud/crud' // 导入自定义组件 import MonitorPointDialogSelector from '../../../../components/selector/MonitorPointDialogSelector' import CriteriaEditor from '../../../../components/CriteriaEditor' const defaultForm = { id: '', warnName: '', warnLevel: '1', sensorTypeCode: '', monitorPointCode: '', sqlStatement: '', description: '', enable: true, sensorCodeList: [], } export default { // 注册导入的组件 components: { MonitorPointDialogSelector, CriteriaEditor, }, mixins: [form(defaultForm)], props: { warnLevels: { type: Array, required: true, }, sensorTypeCodes: { type: Array, required: true, }, }, data() { return { enables: [ { label: '有效', value: true }, { label: '无效', value: false }, ], selectedMonitorPointName: '', monitorPointSensors: [], monitorPointSensorTypeCodes: [], sensorCodes: [], rules: { warnName: [ { required: true, message: '预警名称不能为空', trigger: 'blur', }, ], sqlStatement: [ { required: true, message: '预警SQL不能为空', trigger: 'blur', }, ], }, } }, methods: { // 显示监测点选择对话框 showMonitorPointSelector() { this.selectedMonitorPointName = '' this.$refs.monitorPointSelector.$data.dialogVisible = true }, // 依据获取的监测点选择数据设置字段值 setMonitorPointData(rowData) { // 将获取的数据设置到模型字段中 this.$refs.form.model.monitorPointCode = rowData.id this.selectedMonitorPointName = rowData.monitorPointName // 获取选中监测点绑定的传感器信息 getSensorInfosByMonitorPoint(rowData.id).then((res) => { // console.log(res) this.monitorPointSensors = res this.resetSensorTypeData() }) }, // 重新设置传感器类型 resetSensorTypeData() { if (this.monitorPointSensors.length > 0) { // 清空 this.monitorPointSensorTypeCodes = [] // 获取数据 let tmp = [] this.monitorPointSensors.forEach((item) => { tmp.push(item.deviceTypeCode) }) // 去重 let tmpNoRepeat = [...new Set(tmp)] // 赋值 tmpNoRepeat.forEach((item) => { this.monitorPointSensorTypeCodes.push({ label: this.getSensorTypeName(item), value: item, }) }) // 设置默认值 this.$refs.form.model.sensorTypeCode = tmpNoRepeat[0] // 更新子组件数据 this.$refs.criteriaEditor.updateSensorTypeCode( tmpNoRepeat[0] ) } }, getSensorTypeName(sensorTypeCode) { let sensorTypeName = '' this.sensorTypeCodes.forEach((item) => { if (item.value === sensorTypeCode) { sensorTypeName = item.label } }) return sensorTypeName }, // 依据选中的传感器类型,获取具体的传感器编号 selectSensors(value) { if (this.monitorPointSensors.length > 0) { this.sensorCodes = [] // 依据选中的传感器类型动态更新子组件的数据(props只支持第一次加载时获取数据) // 调用子组件的方法进行更新 this.$refs.criteriaEditor.updateSensorTypeCode(value) this.monitorPointSensors.forEach((item) => { if (item.deviceTypeCode === value) { this.sensorCodes.push(item.id) } }) } }, // 显示SQL编辑器 showCriteriaEditor() { this.$refs.criteriaEditor.$data.dialogVisible = true }, setCriteriaEditorData(data) { this.$refs.form.model.sqlStatement = data }, }, } </script> <style rel="stylesheet/scss" lang="scss" scoped> ::v-deep .el-input-number .el-input__inner { text-align: left; } </style>
<template> <el-dialog append-to-body title="SQL编辑器" :visible.sync="dialogVisible" width="60%" > <!-- 对话框主要内容 --> <el-container> <el-aside width="400px" style="background-color: #fff;"> <el-tree :data="treeData" node-key="id" default-expand-all :expand-on-click-node="false" > <span class="custom-tree-node" slot-scope="{ node, data }" > <span>{{ node.label }}</span> <span v-if="node.id > 1"> <el-button type="text" size="mini" @click="() => remove(node, data)" > 删除 </el-button> </span> </span> </el-tree> </el-aside> <el-container> <el-header style="padding: 0; margin: 0;"> <el-tag size="medium" type="success" style="font-size: 16px;" >{{ '传感器类型:' + sensorTypeName }}</el-tag > </el-header> <el-main> <el-row :gutter="10"> <el-divider content-position="right"> <el-button type="success" size="small" round icon="el-icon-plus" @click="addSubItem" >添加条件项</el-button > </el-divider> </el-row> <el-row :gutter="10" v-for="(criteria, index) in criterias" :key="index" style="padding-bottom: 10px;" > <el-col :span="3" v-if="index > 0"> <el-select v-model="criteria.relation"> <el-option v-for="item in relationSymbols" :key="item.key" :label="item.value" :value="item.key" > </el-option> </el-select> </el-col> <el-col :span="3" v-else> </el-col> <el-col :span="6"> <el-select v-model="criteria.item.property"> <el-option v-for="item in properties" :key="item.property" :label="item.label" :value="item.property" > </el-option> </el-select> </el-col> <el-col :span="4"> <el-select v-model="criteria.compare"> <el-option v-for="item in compareSymbols" :key="item.key" :label="item.value" :value="item.key" > </el-option> </el-select> </el-col> <el-col :span="5"> <el-input-number v-model="criteria.value" :precision="2" :step="0.1" style="width: 100%;" ></el-input-number> </el-col> <el-col :span="1" v-if="index > 0"> <el-button type="danger" circle icon="el-icon-delete" @click="delSubItem(index)" ></el-button> </el-col> </el-row> <el-divider content-position="left"> <el-button type="primary" @click="addCriteriaItem" >添加子条件</el-button > </el-divider> </el-main> </el-container> </el-container> <!-- 对话框底部内容 --> <span slot="footer" class="dialog-footer"> <!-- 确认并关闭对话框,同时,传出选择的行数据 --> <el-button type="primary" @click="selectedAndClose" >确 定</el-button > </span> </el-dialog> </template> <script> let id = 1000 export default { data() { return { dialogVisible: false, sensorTypeCode: '', sensorTypeName: '', treeData: [{ id: 1, label: 'SQL预警条件', children: [] }], criterias: [ { relation: 'and', item: { property: '', label: '' }, compare: '>', value: 0, }, ], properties: [], // 比较符号数组 compareSymbols: [ { key: '=', value: '等于' }, { key: '>', value: '大于' }, { key: '>=', value: '大于等于' }, { key: '<', value: '小于' }, { key: '<=', value: '小于等于' }, ], // 关系符号数组 relationSymbols: [ { key: 'and', value: '且' }, { key: 'or', value: '或' }, ], // 传感器候选项 sensorCandidates: [ { label: '雨量', value: '01', children: [ { property: 'value', label: '降雨量' }, { property: 'totalValue', label: '当日雨量累计', }, ], }, { label: '气温', value: '03', children: [{ property: 'value', label: '温度' }], }, { label: '土压力', value: '04', children: [{ property: 'value', label: '压力' }], }, { label: '地表位移', value: '07', children: [ { property: 'gpsTotalX', label: 'X方向位移' }, { property: 'gpsTotalY', label: 'Y方向位移' }, { property: 'gpsTotalZ', label: 'Z方向位移' }, ], }, { label: '土壤温度', value: '09', children: [{ property: 'value', label: '温度' }], }, { label: '泥水位', value: '10', children: [ { property: 'value', label: '泥水位数据' }, ], }, { label: '孔隙水压力', value: '11', children: [ { property: 'value', label: '孔隙水压力' }, { property: 'temp', label: '孔隙水水温' }, ], }, { label: '土壤含水率', value: '12', children: [{ property: 'value', label: '含水率' }], }, { label: '次声', value: '16', children: [ { property: 'osp', label: '原始声压' }, { property: 'vsp', label: '有效声压' }, { property: 'freq', label: '频率' }, { property: 'wave', label: '波形' }, ], }, { label: '裂缝', value: '17', children: [{ property: 'value', label: '张开度' }], }, { label: '深部位移', value: '22', children: [ { property: 'dispsX', label: '顺滑动方向累计变形量', }, { property: 'dispsY', label: '垂直坡面方向累计变形量', }, ], }, { label: '倾角', value: '23', children: [ { property: 'x', label: 'X轴方向倾角' }, { property: 'y', label: 'Y轴方向倾角' }, { property: 'z', label: 'Z轴方向倾角' }, { property: 'angle', label: 'XY轴合成方位倾角', }, { property: 'trend', label: 'XY轴合成方位角度', }, ], }, { label: '沉降', value: '28', children: [ { property: 'value', label: '单次变化量' }, ], }, { label: '加速度', value: '30', children: [ { property: 'gX', label: 'X轴方向加速度' }, { property: 'gY', label: 'Y轴方向加速度' }, { property: 'gZ', label: 'Z轴方向加速度' }, ], }, { label: '振动', value: '34', children: [ { property: 'plX', label: 'X向振动频率' }, { property: 'plY', label: 'Y向振动频率' }, { property: 'plZ', label: 'Z向振动频率' }, { property: 'value', label: '振动幅度' }, { property: 'sjX', label: 'X向瞬间位移' }, { property: 'sjY', label: 'Y向瞬间位移' }, { property: 'sjZ', label: 'Z向瞬间位移' }, { property: 'sjValue', label: '合方向瞬间位移', }, ], }, { label: '地声', value: '36', children: [ { property: 'osp', label: '原始声压' }, { property: 'vsp', label: '有效声压' }, { property: 'freq', label: '频率' }, { property: 'wave', label: '波形' }, ], }, { label: '地表水位 ', value: '38', children: [ { property: 'value', label: '地表水压力' }, { property: 'temp', label: '地表水水温' }, ], }, { label: '地下水位 ', value: '39', children: [ { property: 'value', label: '地下水压力' }, { property: 'temp', label: '地下水水温' }, ], }, { label: '雷达 ', value: '42', children: [ { property: 'x', label: 'X向坐标' }, { property: 'y', label: 'Y向坐标' }, { property: 'z', label: 'Z向坐标' }, { property: 'speed', label: '移动速度' }, ], }, ], } }, methods: { // props只支持第一次加载这个组件的时候获取父组件的值,后续修改父组件的值得时候子组件并不会动态的更改。 // 动态更新sensorTypeCode数据,该方法被父组件调用 updateSensorTypeCode(value) { this.sensorTypeCode = value console.log('传感器类型:' + this.sensorTypeCode) if (this.sensorTypeCode != '') { this.sensorTypeName = this.sensorCandidates.filter( (item) => item.value === this.sensorTypeCode )[0].label this.properties = this.sensorCandidates.filter( (item) => item.value === this.sensorTypeCode )[0].children } }, selectedAndClose() { // 激发自定义事件,并传递选中数据 this.$emit('confirm', this.buildSql()) // 清空 this.sensorTypeCode = '' this.treeData[0].children = [] // 关闭对话框 this.dialogVisible = false }, remove(node, data) { if (node.id == 1) { return } const parent = node.parent const children = parent.data.children || parent.data const index = children.findIndex((d) => d.id === data.id) children.splice(index, 1) }, addSubItem() { this.criterias.push({ relation: 'and', item: { property: '', label: '' }, compare: '>', value: 0, }) }, delSubItem(index) { this.criterias.splice(index, 1) }, addCriteriaItem() { let where = '' for (let i = 0; i < this.criterias.length; i++) { let criteria = this.criterias[i] let item = criteria.item.property + ' ' + criteria.compare + ' ' + criteria.value if (i == 0) { where = item continue } where += ' ' + criteria.relation + ' ' + item } this.treeData[0].children.push({ id: id++, label: where }) }, buildSql() { let sql = '' for (let i = 0; i < this.treeData[0].children.length; i++) { let item = this.treeData[0].children[i] if (i == 0) { sql = '( ' + item.label + ' )' continue } sql += ' and ( ' + item.label + ' )' } return ( 'select * from ' + this.getTable() + ' where ( ' + sql + ' )' ) }, getTable() { switch (this.sensorTypeCode) { case '01': return 'tbl_jc_yl' case '03': return 'tbl_jc_qw' case '04': return 'tbl_jc_ytyl' case '07': return 'tbl_jc_gnss' case '09': return 'tbl_jc_tw' case '10': return 'tbl_jc_nsw' case '11': return 'tbl_jc_kxsyl' case '12': return 'tbl_jc_trhsl' case '16': return 'tbl_jc_cs' case '17': return 'tbl_jc_lfwy' case '22': return 'tbl_jc_sbwycx' case '23': return 'tbl_jc_qj' case '28': return 'tbl_jc_cj' case '30': return 'tbl_jc_jsd' case '34': return 'tbl_jc_zd' case '36': return 'tbl_jc_ds' case '38': return 'tbl_jc_dbsw' case '39': return 'tbl_jc_dxsw' case '42': return 'tbl_jc_ld' default: return '' } }, }, } </script> <style> .custom-tree-node { flex: 1; display: flex; align-items: center; justify-content: space-between; font-size: 14px; padding-right: 8px; } </style>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。