123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842 |
- <template>
- <el-dialog v-model="isShow" width="60%" @close="closeDialog" destroy-on-close>
- <el-form
- ref="ruleFormRef"
- :model="form"
- :rules="rules"
- label-position="top"
- label-width="200px"
- class="custom-comp-form"
- >
- <el-row
- type="flex"
- justify="space-between"
- align="middle"
- class="first-row"
- :gutter="10"
- >
- <el-col :span="15" class="first-row-first-col">
- <el-form-item prop="name">
- <el-tag size="small">规则名称</el-tag>
- <el-input v-model="form.name" />
- </el-form-item>
- </el-col>
- <el-col :span="9" class="first-row-second-col">
- <el-form-item prop="category">
- <el-tag size="small">报警类别</el-tag>
- <el-select
- v-model="form.category"
- size="mini"
- @change="categorychanged"
- >
- <el-option
- key="1"
- label="风机报警"
- value="windturbine"
- ></el-option>
- <el-option
- key="2"
- label="升压站报警"
- value="booststation"
- ></el-option>
- </el-select>
- </el-form-item>
- <el-form-item prop="rank">
- <el-tag size="small">报警级别</el-tag>
- <el-select v-model="form.rank" size="mini">
- <el-option
- v-for="item in rankList"
- :key="item.id"
- :value="item.id"
- :label="item.name"
- ></el-option>
- </el-select>
- </el-form-item>
- <el-form-item prop="enable">
- <el-tag size="small">是否启用</el-tag>
- <el-switch
- v-model="form.enable"
- :active-value="true"
- :inactive-value="false"
- active-color="#13ce66"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="10" class="second-row">
- <el-col :span="6">
- <el-form-item prop="station">
- <el-tag size="small">{{
- form.category == "windturbine" ? "风场" : "电站"
- }}</el-tag>
- <el-select
- v-model="form.stationId"
- size="mini"
- @change="stationChange"
- >
- <el-option
- v-for="item in stationList"
- :key="item.id"
- :value="item.id"
- :label="item.name"
- />
- </el-select>
- </el-form-item>
- <el-form-item prop="modelId" v-if="form.category == 'windturbine'">
- <el-tag size="small">风机型号</el-tag>
- <el-select
- v-model="form.modelId"
- size="mini"
- @change="modelIdChange"
- >
- <el-option
- v-for="item in state.modelList"
- :key="item"
- :value="item.id"
- :label="item.aname"
- ></el-option>
- </el-select>
- </el-form-item>
- <el-form-item
- prop="relatedParts"
- v-if="form.category == 'windturbine'"
- >
- <el-tag size="small">所属部件</el-tag>
- <el-select v-model="form.relatedParts" style="width: 100%">
- <el-option
- v-for="item in state.relatedPartsList"
- :key="item.nemCode"
- :label="item.name"
- :value="item.nemCode"
- />
- </el-select>
- </el-form-item>
- <el-form-item prop="fault">
- <el-tag size="small">预警类型</el-tag>
- <el-select v-model="form.range" style="width: 100%">
- <el-option
- v-for="i in faultList"
- :key="i.nemCode"
- :value="i.nemCode"
- :label="i.name"
- />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="9">
- <el-form-item prop="expression">
- <el-tag size="small">表达式</el-tag>
- <el-input
- type="textarea"
- rows="14"
- v-model="form.expression"
- id="expressionInput"
- @keyup.z.stop="handle"
- />
- </el-form-item>
- </el-col>
- <el-col :span="9">
- <el-tabs type="border-card">
- <el-tab-pane label="AI测点">
- <el-input v-model="state.AIPointSearch"> </el-input>
- <el-table
- size="mini"
- fit
- :show-header="false"
- stripe
- height="204"
- :data="filterAIList"
- @row-dblclick="rowDbclick"
- >
- <el-table-column prop="uniformCode" width="120" />
- <el-table-column prop="name" />
- </el-table>
- </el-tab-pane>
- <el-tab-pane label="DI测点">
- <el-input v-model="state.DIPointSearch"> </el-input>
- <el-table
- size="mini"
- fit
- :show-header="false"
- stripe
- height="204"
- :data="filterDIList"
- @row-dblclick="rowDbclick"
- >
- <el-table-column prop="uniformCode" width="120" />
- <el-table-column prop="name" />
- </el-table>
- </el-tab-pane>
- <el-tab-pane label="函数">
- <el-table
- size="mini"
- fit
- :show-header="false"
- stripe
- height="204"
- :data="func"
- @row-dblclick="tabFuncRowClickHandle"
- >
- <el-table-column min-width="60%">
- <template #default="scope">
- <el-popover trigger="hover" placement="bottom">
- <p>描述:{{ scope.row.describe }}</p>
- <p>参数:{{ scope.row.param }}</p>
- <template #reference>
- <span size="medium" transition="fade-in-linear">{{
- scope.row.lab
- }}</span>
- </template>
- </el-popover>
- </template>
- </el-table-column>
- <el-table-column min-width="40%">
- <template #default="scope">
- <el-popover trigger="hover" placement="bottom">
- <p>描述:{{ scope.row.describe }}</p>
- <p>参数:{{ scope.row.param }}</p>
- <template #reference>
- <span size="medium" transition="fade-in-linear">{{
- scope.row.name
- }}</span>
- </template>
- </el-popover>
- </template>
- </el-table-column>
- </el-table>
- </el-tab-pane>
- <el-tab-pane label="运算符">
- <div class="operator">
- <el-button
- v-for="item in operator"
- :key="item"
- size="mini"
- class="buttons"
- @click="elInputSplit(item)"
- >
- {{ item }}
- </el-button>
- </div>
- </el-tab-pane>
- </el-tabs>
- </el-col>
- </el-row>
- <el-row :gutter="24">
- <el-col :span="24">
- <el-form-item prop="description">
- <el-tag size="small">规则描述</el-tag>
- <el-input
- type="textarea"
- rows="4"
- v-model="form.description"
- id="descriptionInput"
- />
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- <template #footer>
- <span class="footerButton">
- <el-button round size="mini" @click="closeDialog">取 消</el-button>
- <el-button round size="mini" @click="submitForm(ruleFormRef)"
- >确 定</el-button
- >
- </span>
- </template>
- </el-dialog>
- </template>
- <script setup>
- import {
- ref,
- onMounted,
- reactive,
- computed,
- watch,
- nextTick,
- defineEmits,
- defineProps,
- } from "vue";
- import { ElMessageBox, ElMessage } from "element-plus";
- import {
- custombj_postSave,
- fetch_electrical_point_ai,
- fetch_electrical_point_di,
- getStationinfo,
- fetchPointList,
- fetchPointListByBootst,
- } from "@/api/zhbj/index.js";
- import { useStore } from "vuex";
- const store = useStore();
- const emits = defineEmits(["close"]);
- const props = defineProps({
- //是否显示
- isVisible: {
- type: Boolean,
- defaule: false,
- },
- //表单
- dialogOptions: {
- type: Object,
- },
- //型号接口数据
- modelListAll: {
- type: Object,
- },
- //所属部件及预警类型
- fetchListAll: {
- type: Array,
- },
- //报警级别
- rankList: {
- type: Array,
- },
- });
- watch(
- () => props.isVisible,
- (val, old) => {
- nextTick(() => {
- isShow.value = val;
- });
- },
- {
- deep: true,
- }
- );
- watch(
- () => props.dialogOptions,
- (val, old) => {
- nextTick(() => {
- form.value = val;
- if (val.id && val.id != "") {
- if (val?.stationId.includes("FDC") || val?.stationId.includes("GDC")) {
- getfetchPointList();
- } else {
- getfetchPointListByBootst();
- }
- }
- });
- },
- {
- deep: true,
- }
- );
- watch(
- () => props.dialogOptions?.stationId,
- (val, old) => {
- if (val && val != "") {
- nextTick(async () => {
- state.modelList = props.modelListAll[val];
- if (val.includes("FDC")) {
- state.relatedPartsList = props.fetchListAll?.fjbj;
- } else if (val.includes("GDC")) {
- state.relatedPartsList = props.fetchListAll?.gfbj;
- } else {
- state.relatedPartsList = [];
- }
- });
- } else {
- state.relatedPartsList = [];
- state.modelList = [];
- }
- }
- );
- const isShow = ref(false);
- const form = ref({
- id: "",
- category: "windturbine", //报警类别
- description: "", //描述
- name: "", //规则名称
- enable: true, //是否启用
- expression: "", //表达式
- range: "", //预警类型
- rank: "", //报警级别
- relatedParts: "", //所属部件
- stationId: "", //场站id
- deviceId: "",
- electricalId: "",
- lineId: "",
- modelId: "",
- projectId: "",
- tag: "",
- uniformCode: "",
- });
- const getExtraCharacters = (str1, str2) => {
- let result = "";
- if (str1 && str2) {
- if (str1.length < str2.length) {
- result = str2.slice(str1.length);
- } else if (str1.length > str2.length) {
- result = str1.slice(str2.length);
- }
- }
- return result;
- };
- const newVal = ref("");
- watch(
- () => form.value.expression,
- (val, old) => {
- console.log(val, old);
- let a = getExtraCharacters(val, old);
- newVal.value = a;
- },
- {
- immediate: true,
- }
- );
- // 场站列表/升压站列表
- const stationList = computed(() => {
- if (form.value.category == "windturbine") {
- return store.state.stationListAll;
- } else {
- return store.state.booststationList;
- }
- });
- const toEmits = () => {
- emits("close"); // 向父组件传递数据
- };
- const state = reactive({
- modelList: [], //型号列表
- relatedPartsList: [], //部件列表
- AIPointList: [],
- DIPointList: [],
- AIPointSearch: "",
- DIPointSearch: "",
- });
- const operator = [
- "+",
- "-",
- "*",
- "/",
- "(",
- ")",
- ">",
- ">=",
- "<",
- "<=",
- "==",
- "!=",
- "&&",
- "||",
- "!",
- "%",
- "true",
- "false",
- ".",
- ];
- const func = [
- {
- lab: "MR",
- name: "移动极差",
- param: "测点名,时间(秒)",
- describe: "是指两个或多个连续样本值中最大值与最小值之差",
- scene: "测点的移动极差超限报警",
- },
- {
- lab: "MAR",
- name: "均值极差",
- param: "测点名,时间(秒)",
- describe: "",
- scene: "测点的均值极差计算",
- },
- {
- lab: "RiseExceed",
- name: "上升趋势",
- param: "测点名,时间(秒),阈值",
- describe: "取测点在给定的时间范围内数据上升的量是否超过阈值",
- scene: "测点值的上升速度过快等",
- },
- {
- lab: "Sustain",
- name: "持续时间",
- param: "表达式,时间(秒)",
- describe:
- "判定状态(表达式成立)持续的时间是否超过给定的时间判断状态持续的时间",
- scene: "",
- },
- {
- lab: "LastUpdateTime",
- name: "最近数据时间",
- param: "测点名",
- describe: "",
- scene: "判定离线,状态持续时间等",
- },
- {
- lab: "abs",
- name: "取绝对值",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "acos",
- name: "反余弦",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "asin",
- name: "反正弦",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "atan",
- name: "反正切",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "atan2",
- name: "xy坐标转为极坐标",
- param: "x,y",
- describe: "",
- scene: "",
- },
- {
- lab: "ceiling",
- name: "向上取整",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "cos",
- name: "余弦",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "cosh",
- name: "双曲线余弦",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "exp",
- name: "欧拉数 e 的 double 次幂的值",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "floor",
- name: "向下取整",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "log",
- name: "自然对数",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "log10",
- name: "底数为 10 的对数",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "max",
- name: "比较最大值",
- param: "double a, double b",
- describe: "",
- scene: "",
- },
- {
- lab: "min",
- name: "比较最小值",
- param: "double a, double b",
- describe: "",
- scene: "",
- },
- {
- lab: "pow",
- name: "返回第一个参数的第二个参数次幂的值",
- param: "double a, double b",
- describe: "",
- scene: "",
- },
- {
- lab: "round",
- name: "返回最接近参数的 long,或int",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "sign",
- name: "负数返回-1.0,整数返回1.0,0返回0.0",
- param: "float f/double a",
- describe: "",
- scene: "",
- },
- {
- lab: "sin",
- name: "三角正弦值",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "sinh",
- name: "双曲线正弦",
- param: "double x",
- describe: "",
- scene: "",
- },
- {
- lab: "sqrt",
- name: "正平方根",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "tan",
- name: "正切",
- param: "double a",
- describe: "",
- scene: "",
- },
- {
- lab: "tanh",
- name: "双曲线正切",
- param: "double x",
- describe: "",
- scene: "",
- },
- { lab: "PI", name: "圆周率", param: "", describe: "", scene: "" },
- { lab: "E", name: "自然对数", param: "", describe: "", scene: "" },
- ];
- const faultList = computed(() => props.fetchListAll.yj); //预警类型列表
- const ruleFormRef = ref(null);
- const rules = reactive({
- name: [{ required: true, message: "请输入规则名称", trigger: "blur" }],
- category: [{ required: true, message: "请选择报警类别", trigger: "change" }],
- rank: [{ required: true, message: "请选择报警级别", trigger: "change" }],
- stationId: [{ required: true, message: "请选择风场", trigger: "change" }],
- expression: [
- { required: true, message: "表达式不能为空", trigger: ["change"] },
- ],
- });
- //categorychanged
- const categorychanged = async (val) => {
- form.value.stationId = "";
- form.value.modelId = "";
- form.value.expression = "";
- form.value.relatedParts = "";
- state.AIPointList = [];
- state.DIPointList = [];
- };
- //stationChange
- const stationChange = async (val) => {
- if (form.value.category == "windturbine") {
- form.value.modelId = "";
- state.modelList = props.modelListAll[val];
- } else {
- getfetchPointListByBootst();
- }
- };
- //modelIdChange
- const modelIdChange = async () => {
- getfetchPointList();
- };
- // 根据场站和型号查询测点数据
- const getfetchPointList = async () => {
- const { data } = await fetchPointList(
- form.value.stationId,
- form.value.modelId
- );
- if (Object.keys(data).length) {
- state.AIPointList = data.ai.sort(function (a, b) {
- return a.uniformCode - b.uniformCode;
- });
- state.DIPointList = data.di.sort(function (a, b) {
- return a.uniformCode - b.uniformCode;
- });
- }
- };
- // 根据升压站查询测点数据
- const getfetchPointListByBootst = async () => {
- const { data } = await fetchPointListByBootst(form.value.stationId);
- if (Object.keys(data).length) {
- state.AIPointList = data.ai.sort(function (a, b) {
- return a.uniformCode - b.uniformCode;
- });
- state.DIPointList = data.di.sort(function (a, b) {
- return a.uniformCode - b.uniformCode;
- });
- }
- };
- //筛选AI测点
- const filterAIList = computed(() =>
- state.AIPointList?.filter(
- (data) =>
- !state.AIPointSearch ||
- data.uniformCode.includes(state.AIPointSearch) ||
- data.name.includes(state.AIPointSearch)
- )
- );
- //筛选DI测点
- const filterDIList = computed(() =>
- state.DIPointList?.filter(
- (data) =>
- !state.DIPointSearch ||
- data.uniformCode.includes(state.DIPointSearch) ||
- data.name.includes(state.DIPointSearch)
- )
- );
- // 函数点击事件
- const tabFuncRowClickHandle = (row) => {
- let elInput = document.getElementById("expressionInput");
- let startPos = elInput.selectionStart; //第0个字符到选中的字符
- let endPos = elInput.selectionEnd; //选中字符到末尾字符
- if (startPos === undefined || endPos === undefined) return;
- let txt = elInput.value;
- let func;
- if (
- row.lab === "MR" ||
- row.lab === "MAR" ||
- row.lab === "RiseExceed" ||
- row.lab === "Sustain" ||
- row.lab === "LastUpdateTime"
- ) {
- func = row.lab + "()";
- } else if (row.lab === "PI" || row.lab === "E") {
- func = "Math." + row.lab;
- } else {
- func = "Math." + row.lab + "()";
- }
- // 将插值添加到选中光标位置
- let result = txt.substring(0, startPos) + func + txt.substring(endPos);
- elInput.value = result;
- // 重新定义光标位置
- elInput.focus();
- if (row.lab === "PI" || row.lab === "E") {
- elInput.selectionStart = startPos + func.length;
- elInput.selectionEnd = startPos + func.length;
- } else {
- elInput.selectionStart = startPos + func.length - 1;
- elInput.selectionEnd = startPos + func.length - 1;
- }
- form.value.expression = result; // 赋值给表单中的的字段
- };
- //rowDbclick
- const rowDbclick = (row) => {
- elInputSplit(row);
- };
- // 表达式字符串拼接
- const elInputSplit = async (val) => {
- let elInput = document.getElementById("expressionInput");
- let startPos = elInput.selectionStart;
- let endPos = elInput.selectionEnd;
- if (startPos === undefined || endPos === undefined) return;
- let txt = elInput.value;
- let txtSplit = val.uniformCode || val;
- let result = txt.substring(0, startPos) + txtSplit + txt.substring(endPos);
- elInput.value = result;
- elInput.focus();
- elInput.selectionStart = startPos + txtSplit.length;
- elInput.selectionEnd = startPos + txtSplit.length;
- form.value.expression = result;
- };
- const handle = (e) => {
- if (e.ctrlKey && e.key == "z") {
- form.value.expression = form.value.expression.replace(newVal.value, "");
- }
- };
- //提交
- const submitForm = async (formEl) => {
- if (!formEl) return;
- await formEl.validate((valid, fields) => {
- if (valid) {
- save();
- } else {
- console.log("error submit!", fields);
- }
- });
- };
- //保存
- const save = async () => {
- const res = await custombj_postSave(form.value);
- console.warn(res);
- if (res.code != 200) {
- ElMessage.error(res.msg);
- } else {
- ElMessage.success(`保存成功!`);
- closeDialog();
- }
- };
- //reset
- const resetForm = (formEl) => {
- formEl.resetFields();
- };
- //confirm关闭
- const handleClose = () => {
- ElMessageBox.confirm("确认关闭?")
- .then(() => {
- closeDialog();
- })
- .catch(() => {
- // catch error
- });
- };
- //关闭触发事件
- const closeDialog = () => {
- resetForm(ruleFormRef.value);
- form.value = {};
- state.AIPointList = [];
- state.DIPointList = [];
- toEmits();
- };
- </script>
- <style lang="less" scoped>
- .col-box {
- display: flex;
- flex-direction: column;
- }
- .select-mini {
- width: 120px;
- }
- .el-tabs__content {
- padding: 0 !important;
- }
- .el-tabs--border-card {
- -webkit-box-shadow: none;
- box-shadow: none;
- }
- .border {
- border: solid red 1px;
- }
- .el-table--mini td {
- padding: 3px 0;
- }
- .el-button-group .el-button--primary {
- border: none;
- }
- .el-form--label-top .el-form-item__label {
- padding: 0;
- }
- </style>
|