edit.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. <template>
  2. <div class="system-edit-dic-container">
  3. <el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '告警'" v-model="isShowDialog" width="50%">
  4. <el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="110px">
  5. <el-form-item label="名称" prop="name">
  6. <el-input v-model="ruleForm.name" placeholder="请输入名称" />
  7. </el-form-item>
  8. <el-form-item label="告警级别" prop="level">
  9. <el-radio-group v-model="ruleForm.level">
  10. <el-radio :label="item.level" v-for="item in levelData">{{ item.name }}</el-radio>
  11. </el-radio-group>
  12. </el-form-item>
  13. <el-form-item label="选择产品" prop="productKey">
  14. <el-select v-model="ruleForm.productKey" filterable placeholder="请选择产品" @change="setType()">
  15. <el-option v-for="item in productData" :key="item.key" :label="item.name" :value="item.key">
  16. <span style="float: left">{{ item.name }}</span>
  17. <span style="float: right; font-size: 13px">{{ item.key }}</span>
  18. </el-option>
  19. </el-select>
  20. </el-form-item>
  21. <el-form-item label="选择设备" prop="deviceKey">
  22. <el-select v-model="ruleForm.deviceKey" filterable placeholder="请选择设备">
  23. <el-option v-for="item in sourceData" :key="item.key" :label="item.name" :value="item.key">
  24. <span style="float: left">{{ item.name }}</span>
  25. <span style="float: right; font-size: 13px">{{ item.key }}</span>
  26. </el-option>
  27. </el-select>
  28. </el-form-item>
  29. <el-form-item label="触发方式" prop="triggerType" v-if="ruleForm.productKey">
  30. <el-radio-group v-model="ruleForm.triggerType" @change="getRadio()">
  31. <el-radio :label="item.type" v-for="item in typeData">{{ item.title }}</el-radio>
  32. <el-radio :label="4">事件上报</el-radio>
  33. </el-radio-group>
  34. </el-form-item>
  35. <el-form-item label="选择事件" prop="eventKey" v-if="ruleForm.triggerType===4">
  36. <el-select v-model="ruleForm.eventKey" filterable placeholder="请选择事件" @change="eventTypeChange">
  37. <el-option v-for="item in eventList" :key="item.key" :label="item.name" :value="item.key"></el-option>
  38. </el-select>
  39. </el-form-item>
  40. <el-divider content-position="left">触发条件</el-divider>
  41. <div class="box-content">
  42. <div v-for="(item, index) in requestParams" :key="index">
  43. <div style="text-align: center" v-if="index > 0">
  44. <el-icon><Top /></el-icon>
  45. <div>
  46. <el-select v-model="item.andOr" placeholder="选择条件关系">
  47. <el-option label="无" :value="0" />
  48. <el-option label="并且" :value="1" />
  49. <el-option label="或" :value="2" />
  50. </el-select>
  51. </div>
  52. <el-icon><Bottom /></el-icon>
  53. </div>
  54. <div
  55. style="
  56. padding: 10px;
  57. border: 1px solid var(--next-border-color-light);
  58. background-color: var(--next-border-color-light);
  59. margin-bottom: 10px;
  60. position: relative;
  61. "
  62. >
  63. <div class="conicon" style="width: 100%; text-align: right; position: absolute; right: -8px; top: -8px; color: red">
  64. <el-icon @click="delParams(index)"><CircleClose /></el-icon>
  65. </div>
  66. <div style="display: flex">
  67. <el-divider content-position="left">参数设置</el-divider>
  68. </div>
  69. <div v-for="(aaa, bbb) in item.filters" :key="bbb">
  70. <div style="text-align: center" v-if="bbb > 0">
  71. <el-icon><Top /></el-icon>
  72. <div>
  73. <el-select v-model="aaa.andOr" placeholder="选择条件关系" style="width: 150px">
  74. <el-option label="无" :value="0" />
  75. <el-option label="并且" :value="1" />
  76. <el-option label="或" :value="2" />
  77. </el-select>
  78. </div>
  79. <el-icon><Bottom /></el-icon>
  80. </div>
  81. <div class="content-f">
  82. <el-select v-model="aaa.key" :placeholder="ruleForm.triggerType === 4 && !ruleForm.eventKey ? '请先选择事件' : '选择参数'" style="width: 320px">
  83. <el-option v-for="a in triData" :key="a.paramKey" :label="a.title" :value="a.paramKey" />
  84. </el-select>
  85. <el-select v-model="aaa.operator" placeholder="选择操作符" style="width: 320px">
  86. <el-option v-for="b in operData" :key="b.type" :label="b.title" :value="b.type" />
  87. </el-select>
  88. <el-input v-model="aaa.value" placeholder="请输入条件值" style="width: 320px" />
  89. <div class="conicon">
  90. <el-icon @click="delParamss(index, bbb)"><Delete /></el-icon>
  91. </div>
  92. </div>
  93. </div>
  94. <el-button type="primary" class="addbutton" @click="addParams(index)">增加条件</el-button>
  95. </div>
  96. </div>
  97. </div>
  98. <el-button type="success" class="addbutton" @click="addParamss">增加分组</el-button>
  99. <el-divider content-position="left">执行动作</el-divider>
  100. <div class="box-content">
  101. <div v-for="(item, index) in action" :key="index">
  102. <div
  103. style="
  104. padding: 10px;
  105. border: 1px solid var(--next-border-color-light);
  106. background-color: var(--next-border-color-light);
  107. margin-bottom: 10px;
  108. position: relative;
  109. "
  110. >
  111. <div class="conicon" style="width: 100%; text-align: right; position: absolute; right: -8px; top: -8px; color: red">
  112. <el-icon @click="delAction(index)"><CircleClose /></el-icon>
  113. </div>
  114. <div style="display: flex">
  115. <el-divider content-position="left">消息通知</el-divider>
  116. </div>
  117. <div class="content-f">
  118. <el-select v-model="item.sendGateway" placeholder="请选择通知方式" style="width: 320px" @change="getNode(item.sendGateway, index)">
  119. <el-option v-for="a in notice_send_gateway" :key="a.value" :label="a.label" :value="a.value" />
  120. </el-select>
  121. <el-select v-model="item.noticeConfig" placeholder="请选择通知配置" style="width: 320px" @change="getTem(item.noticeConfig, index)">
  122. <el-option v-for="b in sendGatewayData[index]" :key="b.id" :label="b.title" :value="b.id" />
  123. </el-select>
  124. <el-select v-model="item.noticeTemplate" placeholder="请选择通知模板" style="width: 320px">
  125. <el-option v-for="c in noticeConfigData[index]" :key="c.id" :label="c.title" :value="c.id" />
  126. </el-select>
  127. </div>
  128. <div>
  129. <div style="display: flex; margin-bottom: 10px" v-for="(ph, phindex) in item.addressee" :key="phindex">
  130. <el-input v-model="ph.phone" placeholder="请输入接收人信息" style="width: 320px" />
  131. <el-icon style="width: 32px; height: 32px; font-size: 24px" v-if="phindex == 0" @click="AddPhone(index)"><CirclePlus /></el-icon>
  132. <el-icon style="width: 32px; height: 32px; font-size: 24px" v-if="phindex > 0" @click="DelPhone(index, phindex)"
  133. ><Remove
  134. /></el-icon>
  135. </div>
  136. </div>
  137. </div>
  138. </div>
  139. </div>
  140. <el-button type="success" class="addbutton" @click="addAction">增加执行</el-button>
  141. </el-form>
  142. <template #footer>
  143. <span class="dialog-footer">
  144. <el-button @click="onCancel" size="default">取 消</el-button>
  145. <el-button type="primary" @click="onSubmit" size="default">{{ ruleForm.id !== 0 ? '修 改' : '添 加' }}</el-button>
  146. </span>
  147. </template>
  148. </el-dialog>
  149. </div>
  150. </template>
  151. <script lang="ts">
  152. import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance, watch } from 'vue';
  153. import api from '/@/api/datahub';
  154. import iotapi from '/@/api/device';
  155. import alarm from '/@/api/alarm';
  156. import notice from '/@/api/notice';
  157. import { ElMessage } from 'element-plus';
  158. import { Delete, Plus, CircleClose, Top, Bottom, Minus, Right, CirclePlus, Remove } from '@element-plus/icons-vue';
  159. interface RuleFormState {
  160. id: number;
  161. name: string;
  162. triggerType: number;
  163. level: string;
  164. eventKey: string;
  165. productKey: string;
  166. deviceKey: string;
  167. triggerCondition: string;
  168. }
  169. interface DicState {
  170. isShowDialog: boolean;
  171. ruleForm: RuleFormState;
  172. rules: {};
  173. sourceData: [];
  174. productData: [];
  175. typeData: [];
  176. triData: [];
  177. operData: [];
  178. levelData: [];
  179. requestParams: {};
  180. triggerCondition: {};
  181. action: {};
  182. tempData: {};
  183. sendGatewayData: {};
  184. noticeConfigData: {};
  185. }
  186. export default defineComponent({
  187. name: 'Edit',
  188. components: { Delete, Plus, CircleClose, Minus, Right, Top, Bottom, CirclePlus, Remove },
  189. setup(prop, { emit }) {
  190. const myRef = ref<HTMLElement | null>(null);
  191. const formRef = ref<HTMLElement | null>(null);
  192. const { proxy } = getCurrentInstance() as any;
  193. const { notice_send_gateway } = proxy.useDict('notice_send_gateway');
  194. const state = reactive<DicState>({
  195. id: 0,
  196. isShowDialog: false,
  197. sourceData: [],
  198. tempData: [],
  199. productData: [],
  200. typeData: [],
  201. triData: [],
  202. operData: [],
  203. levelData: [],
  204. sendGatewayData: [],
  205. noticeConfigData: [],
  206. eventList: [],
  207. action: [
  208. {
  209. sendGateway: '',
  210. noticeConfig: '',
  211. noticeTemplate: '',
  212. addressee: [
  213. {
  214. phone: '',
  215. },
  216. ],
  217. },
  218. ],
  219. requestParams: [
  220. {
  221. andOr: '',
  222. filters: [
  223. {
  224. key: '',
  225. operator: '',
  226. value: '',
  227. andOr: 0,
  228. },
  229. ],
  230. },
  231. ],
  232. ruleForm: {
  233. id: 0,
  234. name: '',
  235. triggerType: 1,
  236. eventKey: '',
  237. level: '',
  238. productKey: '',
  239. deviceKey: '',
  240. action: [
  241. {
  242. sendGateway: '',
  243. noticeConfig: '',
  244. noticeTemplate: '',
  245. addressee: {},
  246. },
  247. ],
  248. triggerCondition: [
  249. {
  250. andOr: '',
  251. filters: [
  252. {
  253. key: '',
  254. operator: '',
  255. value: '',
  256. andOr: 0,
  257. },
  258. ],
  259. },
  260. ],
  261. },
  262. rules: {
  263. name: [{ required: true, message: '告警名称不能为空', trigger: 'blur' }],
  264. level: [{ required: true, message: '告警级别不能为空', trigger: 'blur' }],
  265. productKey: [{ required: true, message: '请选择产品', trigger: 'blur' }],
  266. deviceKey: [{ required: true, message: '请选择设备', trigger: 'blur' }],
  267. },
  268. });
  269. // 打开弹窗
  270. const openDialog = (row: RuleFormState | null) => {
  271. resetForm();
  272. getDevData();
  273. if (row) {
  274. alarm.common.detail(row.id).then((res: any) => {
  275. state.requestParams = res.data.condition.triggerCondition;
  276. res.data.performAction.action.forEach(function (value, index) {
  277. notice.config.getList({ sendGateway: value.sendGateway }).then((res: any) => {
  278. state.sendGatewayData[index] = res.Data;
  279. });
  280. if(value.noticeConfig){
  281. notice.template.configIddetail(value.noticeConfig).then((res: any) => {
  282. state.noticeConfigData[index] = [res];
  283. });
  284. }
  285. });
  286. state.action = res.data.performAction.action;
  287. state.action.forEach(function (value, index) {
  288. state.action[index].addressee = value.addressee.map((p) => {
  289. return { phone: p };
  290. });
  291. });
  292. state.ruleForm = res.data;
  293. setType();
  294. });
  295. }
  296. state.isShowDialog = true;
  297. };
  298. //获取设备列表
  299. const getDevData = () => {
  300. iotapi.product.getLists({ status: 1 }).then((res: any) => {
  301. state.productData = res.product || [];
  302. });
  303. alarm.common.levelall('').then((res: any) => {
  304. state.levelData = res.list || [];
  305. });
  306. alarm.common.operator('').then((res: any) => {
  307. state.operData = res.list || [];
  308. });
  309. };
  310. const resetForm = () => {
  311. state.requestParams = [
  312. {
  313. andOr: '',
  314. filters: [
  315. {
  316. key: '',
  317. operator: '',
  318. value: '',
  319. andOr: 0,
  320. },
  321. ],
  322. },
  323. ];
  324. state.action = [
  325. {
  326. sendGateway: '',
  327. noticeConfig: '',
  328. noticeTemplate: '',
  329. addressee: [
  330. {
  331. phone: '',
  332. },
  333. ],
  334. },
  335. ];
  336. state.ruleForm = {
  337. id: 0,
  338. name: '',
  339. triggerType: 1,
  340. level: '',
  341. productKey: '',
  342. deviceKey: '',
  343. action: [
  344. {
  345. sendGateway: '',
  346. noticeConfig: '',
  347. noticeTemplate: '',
  348. addressee: {},
  349. },
  350. ],
  351. triggerCondition: [
  352. {
  353. andOr: '',
  354. filters: [
  355. {
  356. key: '',
  357. operator: '',
  358. value: '',
  359. andOr: 0,
  360. },
  361. ],
  362. },
  363. ],
  364. };
  365. };
  366. // 关闭弹窗
  367. const closeDialog = () => {
  368. state.isShowDialog = false;
  369. };
  370. // 取消
  371. const onCancel = () => {
  372. closeDialog();
  373. };
  374. const eventTypeChange = () => {
  375. setTriData()
  376. };
  377. watch(() => state.ruleForm.productKey, (key) => {
  378. // 切换产品时候重新获取事件列表,清空之前选中的事件
  379. state.ruleForm.eventKey = ''
  380. iotapi.product.event({key}).then((res: any) => {
  381. console.log(res)
  382. })
  383. state.eventList = [{name: '事件1', key: 1}]
  384. })
  385. // 新增
  386. const onSubmit = () => {
  387. const formWrap = unref(formRef) as any;
  388. if (!formWrap) return;
  389. formWrap.validate((valid: boolean) => {
  390. if (valid) {
  391. state.ruleForm.triggerCondition = state.requestParams;
  392. state.action.forEach(function (value, index) {
  393. state.action[index].addressee = value.addressee.map((p) => {
  394. return p.phone;
  395. });
  396. });
  397. state.ruleForm.action = state.action;
  398. if (state.ruleForm.id !== 0) {
  399. //修改
  400. alarm.common.edit(state.ruleForm).then(() => {
  401. ElMessage.success('告警修改成功');
  402. closeDialog(); // 关闭弹窗
  403. emit('typeList');
  404. });
  405. } else {
  406. //添加
  407. alarm.common.add(state.ruleForm).then(() => {
  408. ElMessage.success('告警添加成功');
  409. closeDialog(); // 关闭弹窗
  410. emit('dataList');
  411. });
  412. }
  413. }
  414. });
  415. };
  416. const AddPhone = (index) => {
  417. state.action[index].addressee.push({
  418. phone: '',
  419. });
  420. };
  421. const DelPhone = (index, bbb) => {
  422. state.action[index].addressee.splice(bbb, 1);
  423. };
  424. const addAction = () => {
  425. state.action.push({
  426. sendGateway: '',
  427. noticeConfig: '',
  428. noticeTemplate: '',
  429. addressee: [
  430. {
  431. phone: '',
  432. },
  433. ],
  434. });
  435. };
  436. const delAction = (index) => {
  437. state.action.splice(index, 1);
  438. };
  439. const delParams = (index) => {
  440. state.requestParams.splice(index, 1);
  441. };
  442. const delParamss = (index, bbb) => {
  443. state.requestParams[index].filters.splice(bbb, 1);
  444. };
  445. const addParamss = () => {
  446. state.requestParams.push({
  447. andOr: '',
  448. filters: [
  449. {
  450. key: '',
  451. operator: '',
  452. value: '',
  453. andOr: '',
  454. },
  455. ],
  456. });
  457. };
  458. const addParams = (index) => {
  459. state.requestParams[index].filters.push({
  460. key: '',
  461. operator: '',
  462. value: '',
  463. andOr: '',
  464. });
  465. };
  466. const setType = () => {
  467. let product_id = 0;
  468. state.productData.forEach((item, index) => {
  469. if (item.key == state.ruleForm.productKey) {
  470. product_id = item.id;
  471. }
  472. });
  473. api.common.getdevList({ productId: product_id }).then((res: any) => {
  474. state.sourceData = res.device;
  475. });
  476. alarm.common.trigger_type(state.ruleForm.productKey).then((res: any) => {
  477. state.typeData = res.list || [];
  478. });
  479. gettriData();
  480. };
  481. const getRadio=()=>{
  482. gettriData();
  483. }
  484. const gettriData = () => {
  485. // 清空之前设置的参数设置
  486. state.requestParams = [{
  487. andOr: '',
  488. filters: [
  489. {
  490. key: '',
  491. operator: '',
  492. value: '',
  493. andOr: 0,
  494. },
  495. ],
  496. }]
  497. setTriData()
  498. }
  499. function setTriData() {
  500. // 重置参数列表
  501. state.triData = [];
  502. const triggerType = state.ruleForm.triggerType
  503. const form = {
  504. productKey: state.ruleForm.productKey,
  505. triggerType
  506. }
  507. // 如果是事件上报,需要传eventKey参数
  508. if (triggerType === 4) {
  509. form.eventKey = state.ruleForm.eventKey
  510. if(!form.eventKey) return
  511. }
  512. alarm.common.trigger_params(form).then((res: any) => {
  513. state.triData = res.list || [];
  514. });
  515. }
  516. const getNode = (event, index) => {
  517. state.action[index].noticeConfig = '';
  518. notice.config.getList({ sendGateway: event }).then((res: any) => {
  519. state.sendGatewayData[index] = res.Data;
  520. });
  521. };
  522. const getTem = (event, index) => {
  523. state.action[index].noticeTemplate = '';
  524. notice.template.configIddetail(event).then((res: any) => {
  525. state.noticeConfigData[index] = [res];
  526. });
  527. };
  528. return {
  529. getRadio,
  530. gettriData,
  531. getTem,
  532. getNode,
  533. delAction,
  534. addAction,
  535. eventTypeChange,
  536. AddPhone,
  537. DelPhone,
  538. setType,
  539. addParams,
  540. addParamss,
  541. delParamss,
  542. delParams,
  543. openDialog,
  544. closeDialog,
  545. getDevData,
  546. onCancel,
  547. onSubmit,
  548. formRef,
  549. notice_send_gateway,
  550. myRef,
  551. ...toRefs(state),
  552. };
  553. },
  554. });
  555. </script>
  556. <style>
  557. .inline {
  558. display: inline-flex;
  559. }
  560. .el-input__wrapper {
  561. width: 98%;
  562. }
  563. .box-content {
  564. border: 1px solid #e8e8e8;
  565. margin: 10px;
  566. padding: 10px;
  567. }
  568. .content-f {
  569. display: flex;
  570. margin-bottom: 10px;
  571. }
  572. .content-f .el-input__wrapper {
  573. margin-right: 5px;
  574. }
  575. .addbutton {
  576. width: 100%;
  577. margin-top: 10px;
  578. background: #fff;
  579. border: 1px solid #d1d1d1;
  580. color: #8d8b8b;
  581. }
  582. .conicon {
  583. width: 55px;
  584. height: 25px;
  585. font-size: 28px;
  586. line-height: 28px;
  587. cursor: pointer;
  588. }
  589. .jv-node {
  590. margin-left: 25px;
  591. }
  592. </style>