edit_form.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. <template>
  2. <!-- 编辑弹出框 -->
  3. <el-dialog
  4. :visible="visible"
  5. width="1100px"
  6. :before-close="dialogBeforeClose"
  7. @open="dialogOpenHandle"
  8. @close="dialogCloseHandle"
  9. >
  10. <el-form
  11. ref="form"
  12. :model="form"
  13. :rules="rules"
  14. label-position="top"
  15. label-width="200px"
  16. :disabled="dialogStatus == 2"
  17. >
  18. <el-row type="flex" justify="space-between" align="middle" :gutter="10">
  19. <el-col :span="15">
  20. <el-form-item prop="name">
  21. <el-tag slot="label">规则名称</el-tag>
  22. <el-input v-model="form.name" />
  23. </el-form-item>
  24. </el-col>
  25. <el-col :span="9" style="display:flex;justify-content:space-between;align-items:center">
  26. <el-form-item prop="part">
  27. <el-tag slot="label">工艺环节</el-tag>
  28. <el-select v-model="form.part" class="select-mini">
  29. <el-option key="1" label="预处理" value="pretreatment" />
  30. <el-option key="2" label="干燥塔" value="drying" />
  31. <el-option key="3" label="蒸发车间" value="evaporation" />
  32. </el-select>
  33. </el-form-item>
  34. <el-form-item prop="rank">
  35. <el-tag slot="label">报警级别</el-tag>
  36. <el-select v-model="form.rank" class="select-mini">
  37. <el-option key="1" label="低" :value="1" />
  38. <el-option key="2" label="中低" :value="2" />
  39. <el-option key="3" label="中" :value="3" />
  40. <el-option key="4" label="中高" :value="4" />
  41. <el-option key="5" label="高" :value="5" />
  42. </el-select>
  43. </el-form-item>
  44. <el-form-item prop="enabled">
  45. <el-tag slot="label">是否启用</el-tag>
  46. <el-switch
  47. v-model="form.enabled"
  48. :active-value="true"
  49. :inactive-value="false"
  50. active-color="#13ce66"
  51. />
  52. </el-form-item>
  53. </el-col>
  54. </el-row>
  55. <el-row :gutter="10">
  56. <el-col :span="12">
  57. <el-form-item prop="expression">
  58. <el-tag slot="label">表达式</el-tag>
  59. <el-input
  60. type="textarea"
  61. rows="11"
  62. v-model="form.expression"
  63. :value="form.expression"
  64. id="expressionInput"
  65. />
  66. </el-form-item>
  67. </el-col>
  68. <el-col :span="12">
  69. <el-tabs type="border-card">
  70. <el-tab-pane label="AI测点">
  71. <el-input v-model="AIPointSearch" @input="AIInputChange">
  72. <el-button slot="append" icon="el-icon-search" />
  73. </el-input>
  74. <el-table
  75. size="mini"
  76. fit
  77. :show-header="false"
  78. :highlight-current-row="true"
  79. :stripe="false"
  80. :border="false"
  81. height="200"
  82. :data="AIPointList"
  83. @row-dblclick="tbAI_DBClickHandle"
  84. >
  85. <el-table-column prop="point" />
  86. <el-table-column prop="name" />
  87. </el-table>
  88. </el-tab-pane>
  89. <el-tab-pane label="DI测点">
  90. <el-input v-model="DIPointSearch" @input="DIInputChange">
  91. <el-button slot="append" icon="el-icon-search" />
  92. </el-input>
  93. <el-table
  94. size="mini"
  95. fit
  96. :show-header="false"
  97. :highlight-current-row="true"
  98. :stripe="false"
  99. :border="false"
  100. height="200"
  101. :data="DIPointList"
  102. @row-dblclick="tbDI_DBClickHandle"
  103. >
  104. <el-table-column prop="point" />
  105. <el-table-column prop="name" />
  106. </el-table>
  107. </el-tab-pane>
  108. <el-tab-pane label="函数">
  109. <el-table
  110. size="mini"
  111. fit
  112. :show-header="false"
  113. :highlight-current-row="true"
  114. :stripe="false"
  115. :border="false"
  116. height="230"
  117. :data="func"
  118. @row-dblclick="tabFuncRowClickHandle"
  119. >
  120. <el-table-column min-width="60%">
  121. <template slot-scope="scope">
  122. <el-popover trigger="hover" placement="bottom">
  123. <p>描述:{{ scope.row.describe }}</p>
  124. <p>参数:{{ scope.row.param }}</p>
  125. <div slot="reference">
  126. <span size="medium" transition="fade-in-linear">{{ scope.row.lab }}</span>
  127. </div>
  128. </el-popover>
  129. </template>
  130. </el-table-column>
  131. <el-table-column min-width="40%">
  132. <template slot-scope="scope">
  133. <el-popover trigger="hover" placement="bottom">
  134. <p>描述:{{ scope.row.describe }}</p>
  135. <p>参数:{{ scope.row.param }}</p>
  136. <div slot="reference">
  137. <span size="medium" transition="fade-in-linear">{{ scope.row.name }}</span>
  138. </div>
  139. </el-popover>
  140. </template>
  141. </el-table-column>
  142. </el-table>
  143. </el-tab-pane>
  144. <el-tab-pane label="运算符">
  145. <el-button-group>
  146. <el-button
  147. v-for="item in operator"
  148. :key="item"
  149. plain
  150. type="primary"
  151. @click="btnOperatorClickHandle(item)"
  152. style="width:60px;margin:8px;height:40px"
  153. >{{item}}</el-button>
  154. </el-button-group>
  155. </el-tab-pane>
  156. </el-tabs>
  157. </el-col>
  158. </el-row>
  159. <el-row>
  160. <el-form-item prop="description">
  161. <el-tag slot="label">规则描述</el-tag>
  162. <el-input type="textarea" rows="2" v-model="form.description" />
  163. </el-form-item>
  164. </el-row>
  165. </el-form>
  166. <span slot="footer" class="dialog-footer">
  167. <el-button @click="btnCancelClickHandle">取 消</el-button>
  168. <el-button type="primary" @click="submit">确 定</el-button>
  169. </span>
  170. </el-dialog>
  171. </template>
  172. <script>
  173. import { fetcPointList, alert_rule_postSave } from "../../api/requestAPI";
  174. import axios from "axios";
  175. export default {
  176. data() {
  177. return {
  178. visible: this.isVisible,
  179. isWindturbine: true,
  180. form: {
  181. id: "",
  182. name: "",
  183. description: "",
  184. expression: "",
  185. rank: 1,
  186. enabled: true, // 1可用-0禁用
  187. part: "",
  188. },
  189. AIDataSource: [],
  190. DIDataSource: [],
  191. AIPointList: [],
  192. DIPointList: [],
  193. AIPointSearch: "",
  194. DIPointSearch: "",
  195. func: [
  196. {
  197. lab: "MR",
  198. name: "移动极差",
  199. param: "测点名,时间(秒)",
  200. describe: "是指两个或多个连续样本值中最大值与最小值之差",
  201. scene: "测点的移动极差超限报警",
  202. },
  203. {
  204. lab: "MAR",
  205. name: "均值极差",
  206. param: "测点名,时间(秒)",
  207. describe: "",
  208. scene: "测点的均值极差计算",
  209. },
  210. {
  211. lab: "RiseExceed",
  212. name: "上升趋势",
  213. param: "测点名,时间(秒),阈值",
  214. describe: "取测点在给定的时间范围内数据上升的量是否超过阈值",
  215. scene: "测点值的上升速度过快等",
  216. },
  217. {
  218. lab: "Sustain",
  219. name: "持续时间",
  220. param: "表达式,时间(秒)",
  221. describe:
  222. "判定状态(表达式成立)持续的时间是否超过给定的时间判断状态持续的时间",
  223. scene: "",
  224. },
  225. {
  226. lab: "LastUpdateTime",
  227. name: "最近数据时间",
  228. param: "测点名",
  229. describe: "",
  230. scene: "判定离线,状态持续时间等",
  231. },
  232. {
  233. lab: "abs",
  234. name: "取绝对值",
  235. param: "double a",
  236. describe: "",
  237. scene: "",
  238. },
  239. {
  240. lab: "acos",
  241. name: "反余弦",
  242. param: "double a",
  243. describe: "",
  244. scene: "",
  245. },
  246. {
  247. lab: "asin",
  248. name: "反正弦",
  249. param: "double a",
  250. describe: "",
  251. scene: "",
  252. },
  253. {
  254. lab: "atan",
  255. name: "反正切",
  256. param: "double a",
  257. describe: "",
  258. scene: "",
  259. },
  260. {
  261. lab: "atan2",
  262. name: "xy坐标转为极坐标",
  263. param: "x,y",
  264. describe: "",
  265. scene: "",
  266. },
  267. {
  268. lab: "ceiling",
  269. name: "向上取整",
  270. param: "double a",
  271. describe: "",
  272. scene: "",
  273. },
  274. {
  275. lab: "cos",
  276. name: "余弦",
  277. param: "double a",
  278. describe: "",
  279. scene: "",
  280. },
  281. {
  282. lab: "cosh",
  283. name: "双曲线余弦",
  284. param: "double a",
  285. describe: "",
  286. scene: "",
  287. },
  288. {
  289. lab: "exp",
  290. name: "欧拉数 e 的 double 次幂的值",
  291. param: "double a",
  292. describe: "",
  293. scene: "",
  294. },
  295. {
  296. lab: "floor",
  297. name: "向下取整",
  298. param: "double a",
  299. describe: "",
  300. scene: "",
  301. },
  302. {
  303. lab: "log",
  304. name: "自然对数",
  305. param: "double a",
  306. describe: "",
  307. scene: "",
  308. },
  309. {
  310. lab: "log10",
  311. name: "底数为 10 的对数",
  312. param: "double a",
  313. describe: "",
  314. scene: "",
  315. },
  316. {
  317. lab: "max",
  318. name: "比较最大值",
  319. param: "double a, double b",
  320. describe: "",
  321. scene: "",
  322. },
  323. {
  324. lab: "min",
  325. name: "比较最小值",
  326. param: "double a, double b",
  327. describe: "",
  328. scene: "",
  329. },
  330. {
  331. lab: "pow",
  332. name: "返回第一个参数的第二个参数次幂的值",
  333. param: "double a, double b",
  334. describe: "",
  335. scene: "",
  336. },
  337. {
  338. lab: "round",
  339. name: "返回最接近参数的 long,或int",
  340. param: "double a",
  341. describe: "",
  342. scene: "",
  343. },
  344. {
  345. lab: "sign",
  346. name: "负数返回-1.0,整数返回1.0,0返回0.0",
  347. param: "float f/double a",
  348. describe: "",
  349. scene: "",
  350. },
  351. {
  352. lab: "sin",
  353. name: "三角正弦值",
  354. param: "double a",
  355. describe: "",
  356. scene: "",
  357. },
  358. {
  359. lab: "sinh",
  360. name: "双曲线正弦",
  361. param: "double x",
  362. describe: "",
  363. scene: "",
  364. },
  365. {
  366. lab: "sqrt",
  367. name: "正平方根",
  368. param: "double a",
  369. describe: "",
  370. scene: "",
  371. },
  372. {
  373. lab: "tan",
  374. name: "正切",
  375. param: "double a",
  376. describe: "",
  377. scene: "",
  378. },
  379. {
  380. lab: "tanh",
  381. name: "双曲线余弦",
  382. param: "double x",
  383. describe: "",
  384. scene: "",
  385. },
  386. { lab: "PI", name: "圆周率", param: "", describe: "", scene: "" },
  387. { lab: "E", name: "自然对数", param: "", describe: "", scene: "" },
  388. ],
  389. operator: [
  390. "+",
  391. "-",
  392. "*",
  393. "/",
  394. "(",
  395. ")",
  396. ">",
  397. ">=",
  398. "<",
  399. "<=",
  400. "==",
  401. "!=",
  402. "&&",
  403. "||",
  404. "!",
  405. "%",
  406. "true",
  407. "false",
  408. ".",
  409. ],
  410. rules: {
  411. name: [{ required: true, message: "请输入规则名称", trigger: "blur" }],
  412. part: [
  413. { required: true, message: "请选择工艺环节", trigger: "change" },
  414. ],
  415. rank: [
  416. { required: true, message: "请选择报警级别", trigger: "change" },
  417. ],
  418. expression: [
  419. { required: true, message: "表达式不能为空", trigger: "change" },
  420. ],
  421. },
  422. };
  423. },
  424. props: {
  425. isVisible: Boolean,
  426. dialogStatus: Number, //窗口状态:0-新增;1-修改;2-查看
  427. rowData: Object,
  428. },
  429. watch: {
  430. isVisible(val) {
  431. this.visible = val;
  432. if (val == true) {
  433. this.query_AI_DI_Point();
  434. }
  435. },
  436. rowData(val) {
  437. this.form = JSON.parse(JSON.stringify(val));
  438. },
  439. },
  440. methods: {
  441. // 点击取消事件
  442. btnCancelClickHandle() {
  443. this.visible = false;
  444. this.$emit("cbFunc", this.visible);
  445. },
  446. // 窗口关闭前的回调
  447. dialogBeforeClose(done) {
  448. this.$confirm("确认关闭?")
  449. .then((_) => {
  450. done();
  451. this.visible = false;
  452. this.$emit("cbFunc", this.visible);
  453. })
  454. .catch((_) => {});
  455. },
  456. // 查询风场AI、DI测点
  457. query_AI_DI_Point() {
  458. // 获取AI测点
  459. fetcPointList({ type: "AI" }).then((res) => {
  460. if (res.status == 20000) {
  461. this.AIPointList = res.data;
  462. this.AIDataSource = res.data;
  463. }
  464. });
  465. // 获取DI测点
  466. fetcPointList({ type: "DI" }).then((res) => {
  467. if (res.status == 20000) {
  468. this.DIPointList = res.data;
  469. this.DIDataSource = res.data;
  470. }
  471. });
  472. },
  473. // 函数点击事件
  474. tabFuncRowClickHandle(row) {
  475. let _row = this.deepClone(row);
  476. let elInput = document.getElementById("expressionInput");
  477. let startPos = elInput.selectionStart; //第0个字符到选中的字符
  478. let endPos = elInput.selectionEnd; //选中字符到末尾字符
  479. if (startPos === undefined || endPos === undefined) return;
  480. let txt = elInput.value;
  481. let func;
  482. if (
  483. row.lab === "MR" ||
  484. row.lab === "MAR" ||
  485. row.lab === "RiseExceed" ||
  486. row.lab === "Sustain" ||
  487. row.lab === "LastUpdateTime"
  488. ) {
  489. func = row.lab + "()";
  490. } else if (row.lab === "PI" || row.lab === "E") {
  491. func = "Math." + row.lab;
  492. } else {
  493. func = "Math." + row.lab + "()";
  494. }
  495. // 将插值添加到选中光标位置
  496. let result = txt.substring(0, startPos) + func + txt.substring(endPos);
  497. elInput.value = result;
  498. // 重新定义光标位置
  499. elInput.focus();
  500. if (row.lab === "PI" || row.lab === "E") {
  501. elInput.selectionStart = startPos + func.length;
  502. elInput.selectionEnd = startPos + func.length;
  503. } else {
  504. elInput.selectionStart = startPos + func.length - 1;
  505. elInput.selectionEnd = startPos + func.length - 1;
  506. }
  507. this.form.expression = result; // 赋值给表单中的的字段
  508. },
  509. // 运算符点击事件
  510. btnOperatorClickHandle(row) {
  511. this.elInputSplit(row);
  512. },
  513. //提交表单
  514. submit() {
  515. this.form.expression = document.getElementById("expressionInput").value;
  516. this.$refs["form"].validate((valid) => {
  517. if (valid) {
  518. this.$confirm("确认关闭?")
  519. .then(() => {
  520. console.log(this.form);
  521. console.log(this.dialogStatus);
  522. switch (this.dialogStatus) {
  523. //窗口状态:0-新增;1-修改;2-查看
  524. case 0:
  525. alert_rule_postSave(this.form)
  526. .then((response) => {
  527. console.log(response.data.status);
  528. if (response.data.status == 20000) {
  529. this.$message.success("保存成功");
  530. // 关闭窗口
  531. this.visible = false;
  532. this.$emit("cbFunc", this.visible);
  533. } else if (
  534. response.data.status == 5000 ||
  535. response.data.status == 5001
  536. ) {
  537. this.$message.error("未登陆,或登陆失效");
  538. this.$router.push("/login");
  539. } else if (response.data.status == 5002) {
  540. this.$message.error(response.data.msg);
  541. }
  542. })
  543. .catch((err) => {
  544. console.log(err);
  545. });
  546. break;
  547. case 1:
  548. alert_rule_postSave(this.form)
  549. .then((response) => {
  550. if (response.data.success) {
  551. this.$message.success("保存成功");
  552. // 关闭窗口
  553. this.visible = false;
  554. this.$emit("cbFunc", this.visible);
  555. } else if (
  556. response.data.status != null &&
  557. response.data.status == 521
  558. ) {
  559. this.$message.error("登陆过期");
  560. this.$router.push("/login");
  561. return;
  562. } else {
  563. this.$message.error(response.data.msg);
  564. }
  565. })
  566. .catch((err) => {
  567. console.log(err);
  568. });
  569. break;
  570. default:
  571. // 关闭窗口
  572. this.visible = false;
  573. this.$emit("cbFunc", this.visible);
  574. break;
  575. }
  576. })
  577. .catch((err) => {
  578. console.log(err);
  579. });
  580. }
  581. });
  582. },
  583. // 窗口打开事件 - 做重置表单操作
  584. dialogOpenHandle() {
  585. // 重置表单
  586. if (this.dialogStatus === 0) {
  587. this.isWindturbine = true;
  588. (this.AIDataSource = []),
  589. (this.DIDataSource = []),
  590. (this.AIPointList = []),
  591. (this.DIPointList = []),
  592. (this.AIPointSearch = ""),
  593. (this.DIPointSearch = ""),
  594. (this.form = { enabled: "1" });
  595. if (this.$refs["form"] != undefined) {
  596. this.$refs["form"].resetFields();
  597. }
  598. } else {
  599. this.AIPointSearch = "";
  600. this.DIPointSearch = "";
  601. }
  602. },
  603. // 窗口关闭事件 - 做重置表单操作
  604. dialogCloseHandle() {
  605. // 重置表单
  606. if (this.dialogStatus === 0) {
  607. this.isWindturbine = true;
  608. (this.AIDataSource = []),
  609. (this.DIDataSource = []),
  610. (this.AIPointList = []),
  611. (this.DIPointList = []),
  612. (this.AIPointSearch = ""),
  613. (this.DIPointSearch = ""),
  614. (this.form = { enabled: "1" });
  615. if (this.$refs["form"] != undefined) {
  616. this.$refs["form"].resetFields();
  617. }
  618. } else {
  619. this.AIPointSearch = "";
  620. this.DIPointSearch = "";
  621. }
  622. },
  623. // AI测点模糊查询
  624. AIInputChange() {
  625. this.AIPointList = this.AIDataSource.filter((i) => {
  626. return i.name.indexOf(this.AIPointSearch) != -1;
  627. });
  628. },
  629. // DI测点模糊查询
  630. DIInputChange() {
  631. this.DIPointList = this.DIDataSource.filter((i) => {
  632. return i.name.indexOf(this.DIPointSearch) != -1;
  633. });
  634. },
  635. tbAI_DBClickHandle(row) {
  636. this.elInputSplit(row.point);
  637. },
  638. tbDI_DBClickHandle(row) {
  639. this.elInputSplit(row.point);
  640. },
  641. deepClone(obj) {
  642. let _obj = JSON.stringify(obj),
  643. objClone = JSON.parse(_obj);
  644. return objClone;
  645. },
  646. // 表达式字符串拼接
  647. elInputSplit(val) {
  648. let elInput = document.getElementById("expressionInput");
  649. let startPos = elInput.selectionStart;
  650. let endPos = elInput.selectionEnd;
  651. if (startPos === undefined || endPos === undefined) return;
  652. let txt = elInput.value;
  653. let txtSplit = val;
  654. let result =
  655. txt.substring(0, startPos) + txtSplit + txt.substring(endPos);
  656. elInput.value = result;
  657. elInput.focus();
  658. elInput.selectionStart = startPos + txtSplit.length;
  659. elInput.selectionEnd = startPos + txtSplit.length;
  660. // this.form.expression = result;
  661. },
  662. },
  663. };
  664. </script>
  665. <style>
  666. .col-box {
  667. display: flex;
  668. flex-direction: column;
  669. }
  670. .select-mini {
  671. width: 120px;
  672. }
  673. .el-tabs__content {
  674. padding: 0 !important;
  675. }
  676. .el-tabs--border-card {
  677. -webkit-box-shadow: none;
  678. box-shadow: none;
  679. }
  680. .border {
  681. border: solid red 1px;
  682. }
  683. .el-table--mini td {
  684. padding: 3px 0;
  685. }
  686. .el-button-group .el-button--primary {
  687. border: none;
  688. }
  689. .el-form--label-top .el-form-item__label {
  690. padding: 0;
  691. }
  692. </style>