linkRules.vue 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  1. <template>
  2. <a-card>
  3. <a-row justify="space-between" >
  4. <a-col :span="12" >
  5. <a-space>
  6. <a-input placeholder="请填写规则名称" v-model:value="queryParamsState.ruleLabel" ></a-input>
  7. <a-button type="primary" @click="getLinkPage()" >搜索</a-button>
  8. </a-space>
  9. </a-col>
  10. <a-col>
  11. <a-space>
  12. <a-button type="primary" @click="openModal('add', {})" >创建规则</a-button>
  13. </a-space>
  14. </a-col>
  15. </a-row>
  16. <a-table
  17. style="margin-top: 20px;"
  18. :columns="columns"
  19. :data-source="state.dataSource"
  20. :loading="state.loading"
  21. :pagination="queryParamsState"
  22. @change="changePage"
  23. >
  24. <template #bodyCell="{column, record}" >
  25. <template v-if="column.key === 'status'" >
  26. <a-switch
  27. v-model:checked="record.status"
  28. checked-children="运行中"
  29. un-checked-children="已停止"
  30. @click="changeStatus(record)"
  31. />
  32. </template>
  33. <template v-if="column.key === 'action'" >
  34. <a-space>
  35. <a @click="openModal('preview', record)" >详情</a>
  36. <a @click="openModal('update', record)" >编辑</a>
  37. <a-popconfirm
  38. title="确实要删除吗?"
  39. ok-text="确定"
  40. cancel-text="取消"
  41. @confirm="delLinkRule(record.id)"
  42. >
  43. <a>删除</a>
  44. </a-popconfirm>
  45. </a-space>
  46. </template>
  47. </template>
  48. </a-table>
  49. </a-card>
  50. <modal-pro
  51. style="width: 1400px;"
  52. :label=" state.opraState !== 'preview' ? '创建转发规则' : '查看详情'"
  53. :visible="state.visible"
  54. @cancel="state.visible = false"
  55. @ok="ok"
  56. >
  57. <div style="height: 750px;overflow: hidden;overflow-y: auto;">
  58. <a-card
  59. title="基本信息"
  60. :bordered="false"
  61. >
  62. <a-form :labelCol="{span: 2}" :wapperCol="{span: 12}" >
  63. <a-form-item label="规则名称" v-bind="validateInfos.ruleLabel">
  64. <span v-if=" state.opraState === 'preview'" >{{bodyParamsState.ruleLabel}}</span>
  65. <a-input v-else v-model:value="bodyParamsState.ruleLabel" ></a-input>
  66. </a-form-item >
  67. <a-form-item label='规则描述'>
  68. <span v-if=" state.opraState === 'preview'" >{{bodyParamsState.ruleDescription}}</span>
  69. <a-textarea
  70. v-else
  71. v-model:value="bodyParamsState.ruleDescription"
  72. placeholder="请输入规则描述"
  73. :auto-size="{ minRows: 2, maxRows: 5 }"
  74. />
  75. </a-form-item>
  76. </a-form>
  77. </a-card>
  78. <a-card
  79. title="触发条件"
  80. :bordered="false"
  81. >
  82. <a-row class="condition" >
  83. <a-col span="12" >
  84. 需满足
  85. <span v-if="state.opraState === 'preview'">{{bodyParamsState.conditionLogic}}</span>
  86. <a-dropdown v-else>
  87. <a class="ant-dropdown-link" @click.prevent>
  88. {{bodyParamsState.conditionLogic === 'AND' ? '全部' : '任意一个'}}
  89. <DownOutlined />
  90. </a>
  91. <template #overlay>
  92. <a-menu>
  93. <a-menu-item @click="changeConditionLogic('AND')" >
  94. <a >全部</a>
  95. </a-menu-item>
  96. <a-menu-item @click="changeConditionLogic('ALL')">
  97. <a >任意一个</a>
  98. </a-menu-item>
  99. </a-menu>
  100. </template>
  101. </a-dropdown>
  102. 以下条件:
  103. </a-col>
  104. <a-col class="df" span="12" >
  105. <a-button v-if="state.opraState !== 'preview'" type="primary" @click="openFormVisible('conditions')">添加条件</a-button>
  106. </a-col>
  107. <a-col :span="24" v-if="deviceDataSource.length" >
  108. <a-table
  109. style="width: 100%;margin-top: 10px;"
  110. :columns="state.opraState !== 'preview' ? conditionColumns.DEVICE_DATA : conditionColumns.DEVICE_DATA.slice(0, conditionColumns.DEVICE_DATA.length - 1)"
  111. :data-source="deviceDataSource"
  112. size="small"
  113. :pagination="false"
  114. >
  115. <template #bodyCell="{column, record}" >
  116. <template v-if="column.key === 'action'" >
  117. <a @click="delCondiTionsAndActions(record.id, 'conditions')" >
  118. 删除
  119. </a>
  120. </template>
  121. </template>
  122. </a-table>
  123. </a-col>
  124. <a-col :span="24" v-if="deviceSessionSource.length" >
  125. <a-table
  126. style="width: 100%;margin-top: 10px;"
  127. :columns="state.opraState !== 'preview' ? conditionColumns.DEVICE_SESSION : conditionColumns.DEVICE_SESSION.slice(0, conditionColumns.DEVICE_SESSION.length - 1)"
  128. :data-source="deviceSessionSource"
  129. size="small"
  130. :pagination="false"
  131. >
  132. <template #bodyCell="{column, record}" >
  133. <template v-if="column.key === 'sessionEventType'" >
  134. {{record.sessionEventType === 'CONNECT' ? '连接' : '断开连接' }}
  135. </template>
  136. <template v-if="column.key === 'action'" >
  137. <a @click="delCondiTionsAndActions(record.id, 'conditions')" >
  138. 删除
  139. </a>
  140. </template>
  141. </template>
  142. </a-table>
  143. </a-col>
  144. <a-col :span="24" v-if="dailyTimerSource.length" >
  145. <a-table
  146. style="width: 100%;margin-top: 10px;"
  147. :columns="state.opraState !== 'preview' ? conditionColumns.DAILY_TIMER : conditionColumns.DAILY_TIMER.slice(0, conditionColumns.DAILY_TIMER.length - 1)"
  148. :data-source="dailyTimerSource"
  149. size="small"
  150. :pagination="false"
  151. >
  152. <template #bodyCell="{column, record}" >
  153. <template v-if="column.key === 'dayOfWeek'" >
  154. {{record.dayOfWeek.map(item => '周' + item).join(',') }}
  155. </template>
  156. <template v-if="column.key === 'time'" >
  157. {{record.time}}
  158. </template>
  159. <template v-if="column.key === 'action'" >
  160. <a @click="delCondiTionsAndActions(record.id, 'conditions')" >
  161. 删除
  162. </a>
  163. </template>
  164. </template>
  165. </a-table>
  166. </a-col>
  167. <a-col v-if="bodyParamsState.conditions.length === 0" class="content" >尚未设置条件</a-col>
  168. </a-row>
  169. </a-card>
  170. <a-card
  171. title="执行动作"
  172. :bordered="false"
  173. >
  174. <a-row style="width: 100%;" >
  175. <a-col :span="24" class="df" ><a-button v-if="state.opraState !== 'preview'" type="primary" @click="openFormVisible('actions')" >添加动作</a-button></a-col>
  176. <a-row style="width: 100%;" v-if="bodyParamsState.actions.length">
  177. <a-col :span="24" v-if="deviceCmdsource.length" >
  178. <a-table
  179. style="width: 100%;margin-top: 10px;"
  180. :columns="state.opraState !== 'preview' ? actionsColumns.DEVICE_CMD : actionsColumns.DEVICE_CMD.slice(0, actionsColumns.DEVICE_CMD.length - 1)"
  181. :data-source="deviceCmdsource"
  182. size="small"
  183. :pagination="false"
  184. >
  185. <template #bodyCell="{column, record}" >
  186. <template v-if="column.key === 'action'" >
  187. <a @click="delCondiTionsAndActions(record.id, 'actions')" >
  188. 删除
  189. </a>
  190. </template>
  191. </template>
  192. </a-table>
  193. </a-col>
  194. <a-col :span="24" v-if="reportWarnSource.length" >
  195. <a-table
  196. style="width: 100%;margin-top: 10px;"
  197. :columns="state.opraState !== 'preview' ? actionsColumns.REPORT_WARN : actionsColumns.REPORT_WARN.slice(0, actionsColumns.REPORT_WARN.length - 1)"
  198. :data-source="reportWarnSource"
  199. size="small"
  200. :pagination="false"
  201. >
  202. <template #bodyCell="{column, record}" >
  203. <template v-if="column.key === 'action'" >
  204. <a @click="delCondiTionsAndActions(record.id, 'actions')" >
  205. 删除
  206. </a>
  207. </template>
  208. </template>
  209. </a-table>
  210. </a-col>
  211. <a-col :span="24" v-if="resumeWarnSource.length" >
  212. <a-table
  213. style="width: 100%;margin-top: 10px;"
  214. :columns="state.opraState !== 'preview' ? actionsColumns.RESUME_WARN : actionsColumns.RESUME_WARN.slice(0, actionsColumns.RESUME_WARN.length - 1)"
  215. :data-source="resumeWarnSource"
  216. size="small"
  217. :pagination="false"
  218. >
  219. <template #bodyCell="{column, record}" >
  220. <template v-if="column.key === 'action'" >
  221. <a @click="delCondiTionsAndActions(record.id, 'actions')" >
  222. 删除
  223. </a>
  224. </template>
  225. </template>
  226. </a-table>
  227. </a-col>
  228. <a-col :span="24" v-if="noticeSource.length" >
  229. <a-table
  230. style="width: 100%;margin-top: 10px;"
  231. :columns="state.opraState !== 'preview' ? actionsColumns.NOTICE : actionsColumns.NOTICE.slice(0, actionsColumns.NOTICE.length - 1)"
  232. :data-source="noticeSource"
  233. size="small"
  234. :pagination="false"
  235. >
  236. <template #bodyCell="{column, record}" >
  237. <template v-if="column.key === 'action'" >
  238. <a @click="delCondiTionsAndActions(record.id, 'actions')" >
  239. 删除
  240. </a>
  241. </template>
  242. </template>
  243. </a-table>
  244. </a-col>
  245. </a-row>
  246. <a-col class="content" v-if="bodyParamsState.actions.length === 0" >尚未设置动作</a-col>
  247. </a-row>
  248. </a-card>
  249. </div>
  250. </modal-pro>
  251. <modal-pro
  252. label="选择"
  253. :visible="state.formVisible"
  254. @cancel="state.formVisible = false"
  255. @ok="selectConditionAndAction"
  256. style="width: 700px;"
  257. >
  258. <div style="width: 100%;" v-if="state.opraModel === 'conditions'" >
  259. <a-row :gutter="[8, 8]" style="width: 100%;" >
  260. <a-form
  261. style="width: 100%;"
  262. :label-col="{ span: 3 }"
  263. :wrapper-col="{ span: 16 }"
  264. >
  265. <a-col>
  266. <a-form-item label="触发条件" >
  267. <a-select
  268. style="width: 170px"
  269. v-model:value="initConditionsData.conditionType"
  270. >
  271. <a-select-option
  272. v-for="itemType in conditionTypeList"
  273. :key="itemType.key"
  274. :value="itemType.key"
  275. >
  276. {{itemType.name}}
  277. </a-select-option>
  278. </a-select>
  279. </a-form-item>
  280. <span v-if="initConditionsData.conditionType === 'DEVICE_DATA'" >
  281. <a-form-item label="产品" >
  282. <a-select
  283. style="width: 170px"
  284. placeholder="请选择产品"
  285. v-model:value="initConditionsData.modelId"
  286. >
  287. <a-select-option
  288. v-for="model in state.modelList"
  289. :key="model.id"
  290. :value="model.id"
  291. >
  292. {{model.modelLabel}}
  293. </a-select-option>
  294. </a-select>
  295. </a-form-item>
  296. <a-form-item label="设备类型" >
  297. <a-space>
  298. <a-select
  299. style="width: 170px"
  300. placeholder="请选择设备"
  301. v-model:value="initConditionsData.deviceType"
  302. >
  303. <a-select-option
  304. v-for="deviceItem in selectDeviceList"
  305. :key="deviceItem.key"
  306. :value="deviceItem.key"
  307. >
  308. {{deviceItem.name}}
  309. </a-select-option>
  310. </a-select>
  311. <a-tag color="blue" v-if="initConditionsData.deviceLabel" >{{initConditionsData.deviceLabel}}</a-tag>
  312. <a-button
  313. type="primary"
  314. v-if="initConditionsData.deviceType === 'target'"
  315. @click="openDeviceModal('conditions')"
  316. >
  317. {{initConditionsData.deviceId ? '重新选择' : '请选择设备'}}
  318. </a-button>
  319. </a-space>
  320. </a-form-item>
  321. <a-form-item label="属性key" >
  322. <a-select
  323. style="width: 170px"
  324. placeholder="请选择属性key"
  325. v-model:value="initConditionsData.attributeKey"
  326. >
  327. <a-select-option
  328. v-for="attrItem in state.attrList"
  329. :key="attrItem.attributeKey"
  330. :value="attrItem.attributeKey"
  331. >
  332. {{attrItem.attributeKey}}
  333. </a-select-option>
  334. </a-select>
  335. </a-form-item>
  336. <a-form-item label="操作符" >
  337. <a-select
  338. style="width: 170px"
  339. placeholder="请选择操作符"
  340. v-model:value="initConditionsData.operator"
  341. >
  342. <a-select-option
  343. v-for="operaItem in operatorList"
  344. :key="operaItem"
  345. :value="operaItem"
  346. >
  347. {{operaItem}}
  348. </a-select-option>
  349. </a-select>
  350. </a-form-item>
  351. <a-form-item label="触发值" >
  352. <a-input
  353. v-if="initConditionsData.operator !== 'BETWEEN'"
  354. style="width: 170px;"
  355. placeholder="请选择触发值"
  356. v-model:value="initConditionsData.value"
  357. ></a-input>
  358. <a-input-group compact v-else >
  359. <a-input placeholder="值1" v-model:value="initConditionsData.v1" style="width: 20%" />
  360. <a-input placeholder="值2" v-model:value="initConditionsData.v2" style="width: 30%" />
  361. </a-input-group>
  362. </a-form-item>
  363. </span>
  364. <span v-else-if="initConditionsData.conditionType === 'DEVICE_SESSION'" >
  365. <a-form-item label="产品">
  366. <a-select
  367. style="width: 170px"
  368. placeholder="请选择产品"
  369. v-model:value="initConditionsData.modelId"
  370. >
  371. <a-select-option
  372. v-for="model in state.modelList"
  373. :key="model.id"
  374. :value="model.id"
  375. >
  376. {{model.modelLabel}}
  377. </a-select-option>
  378. </a-select>
  379. </a-form-item>
  380. <a-form-item label="设备类型" >
  381. <a-space>
  382. <a-select
  383. style="width: 170px"
  384. placeholder="请选择设备"
  385. v-model:value="initConditionsData.deviceType"
  386. >
  387. <a-select-option
  388. v-for="deviceItem in selectDeviceList"
  389. :key="deviceItem.key"
  390. :value="deviceItem.key"
  391. >
  392. {{deviceItem.name}}
  393. </a-select-option>
  394. </a-select>
  395. <a-tag color="blue" v-if="initConditionsData.deviceLabel" >{{initConditionsData.deviceLabel}}</a-tag>
  396. <a-button
  397. type="primary"
  398. v-if="initConditionsData.deviceType === 'target'"
  399. @click="openDeviceModal('conditions')"
  400. >
  401. {{initConditionsData.deviceId ? '重新选择' : '请选择设备'}}
  402. </a-button>
  403. </a-space>
  404. </a-form-item>
  405. <a-form-item label="是否连接" >
  406. <a-select
  407. style="width: 170px"
  408. placeholder="请选择session"
  409. v-model:value="initConditionsData.sessionEventType"
  410. >
  411. <a-select-option
  412. v-for="essionEventTypeItem in sessionEventTypeList"
  413. :key="essionEventTypeItem.key"
  414. :value="essionEventTypeItem.key"
  415. >
  416. {{essionEventTypeItem.name}}
  417. </a-select-option>
  418. </a-select>
  419. </a-form-item>
  420. </span>
  421. <span v-else-if="initConditionsData.conditionType === 'DAILY_TIMER'" >
  422. <a-form-item label="时间" >
  423. <a-checkbox-group v-model:value="initConditionsData.dayOfWeek" :options="dayOptions" />
  424. </a-form-item>
  425. <a-form-item label="日期" >
  426. <a-time-picker v-model:value="initConditionsData.time" value-format="HH:mm:ss" />
  427. </a-form-item>
  428. </span>
  429. </a-col>
  430. </a-form>
  431. </a-row>
  432. </div>
  433. <div v-else style="width: 100%;" >
  434. <a-row :gutter="[8, 8]" style="width: 100%;" >
  435. <a-form
  436. style="width: 100%;"
  437. :label-col="{ span: 3 }"
  438. :wrapper-col="{ span: 16 }"
  439. >
  440. <a-col>
  441. <a-form-item label="触发动作" >
  442. <a-select
  443. style="width: 170px"
  444. v-model:value="initActionsData.actionType"
  445. >
  446. <a-select-option
  447. v-for="actionItem in actionTypeList"
  448. :key="actionItem.key"
  449. :value="actionItem.key"
  450. >
  451. {{actionItem.name}}
  452. </a-select-option>
  453. </a-select>
  454. </a-form-item>
  455. </a-col>
  456. <span v-if="initActionsData.actionType === 'DEVICE_CMD'" >
  457. <a-col>
  458. <a-form-item label="选择产品" >
  459. <a-select
  460. style="width: 170px"
  461. placeholder="请选择产品"
  462. v-model:value="initActionsData.modelId"
  463. >
  464. <a-select-option
  465. v-for="model in state.modelList"
  466. :key="model.id"
  467. :value="model.id"
  468. >
  469. {{model.modelLabel}}
  470. </a-select-option>
  471. </a-select>
  472. </a-form-item>
  473. <a-form-item label="设备类型" >
  474. <a-space>
  475. <a-select
  476. style="width: 170px"
  477. placeholder="请选择设备"
  478. v-model:value="initActionsData.deviceType"
  479. >
  480. <a-select-option
  481. v-for="deviceItem in selectDeviceList"
  482. :key="deviceItem.key"
  483. :value="deviceItem.key"
  484. >
  485. {{deviceItem.name}}
  486. </a-select-option>
  487. </a-select>
  488. <a-tag color="blue" v-if="initActionsData.deviceLabel" >{{initActionsData.deviceLabel}}</a-tag>
  489. <a-button
  490. type="primary"
  491. v-if="initActionsData.deviceType === 'target'"
  492. @click="openDeviceModal('actions')"
  493. >
  494. {{initActionsData.deviceId ? '重新选择' : '请选择设备'}}
  495. </a-button>
  496. </a-space>
  497. </a-form-item>
  498. <a-form-item label="选择命令" >
  499. <a-select
  500. style="width: 170px;"
  501. v-model:value="initActionsData.cmdId"
  502. >
  503. <a-select-option
  504. v-for="cmdItem in state.cmdList"
  505. :key="cmdItem.id"
  506. :value="cmdItem.id"
  507. >
  508. {{cmdItem.cmdLabel}}
  509. </a-select-option>
  510. </a-select>
  511. </a-form-item>
  512. <a-form-item label="命令参数" >
  513. <div
  514. v-for="(item, index) in initActionsData.cmdParameters"
  515. :key="index"
  516. style="margin-bottom: 10px;"
  517. >
  518. <a-input-group compact >
  519. <a-input placeholder="key" disabled v-model:value="item.paramLabel" style="width: 50%" />
  520. <a-input placeholder="value" v-model:value="item.dataUnit" style="width: 50%" />
  521. </a-input-group>
  522. </div>
  523. </a-form-item>
  524. </a-col>
  525. </span>
  526. <span v-else-if="initActionsData.actionType === 'REPORT_WARN'">
  527. <a-form-item label="设备类型" >
  528. <a-space>
  529. <a-select
  530. style="width: 170px"
  531. placeholder="请选择设备"
  532. v-model:value="initActionsData.deviceType"
  533. >
  534. <a-select-option
  535. v-for="deviceItem in selectDeviceList"
  536. :key="deviceItem.key"
  537. :value="deviceItem.key"
  538. >
  539. {{deviceItem.name}}
  540. </a-select-option>
  541. </a-select>
  542. <a-tag color="blue" v-if="initActionsData.deviceLabel" >{{initActionsData.deviceLabel}}</a-tag>
  543. <a-button
  544. type="primary"
  545. v-if="initActionsData.deviceType === 'target'"
  546. @click="openDeviceModal('actions')"
  547. >
  548. {{initActionsData.deviceId ? '重新选择' : '请选择设备'}}
  549. </a-button>
  550. </a-space>
  551. </a-form-item>
  552. <a-form-item label="告警名称" >
  553. <a-input v-model:value="initActionsData.warnLabel" ></a-input>
  554. </a-form-item>
  555. <a-form-item label="告警描述" >
  556. <a-input v-model:value="initActionsData.warnDescription" ></a-input>
  557. </a-form-item>
  558. <a-form-item label="告警级别" >
  559. <a-select v-model:value="initActionsData.warnSeverity" >
  560. <a-select-option
  561. v-for='warnItem in warnSeverityList'
  562. :key="warnItem.key"
  563. :value="warnItem.key"
  564. >
  565. {{warnItem.name}}
  566. </a-select-option>
  567. </a-select>
  568. </a-form-item>
  569. </span>
  570. <span v-else-if="initActionsData.actionType === 'RESUME_WARN'">
  571. <a-form-item label="设备类型" >
  572. <a-space>
  573. <a-select
  574. style="width: 170px"
  575. placeholder="请选择设备"
  576. v-model:value="initActionsData.deviceType"
  577. >
  578. <a-select-option
  579. v-for="deviceItem in selectDeviceList"
  580. :key="deviceItem.key"
  581. :value="deviceItem.key"
  582. >
  583. {{deviceItem.name}}
  584. </a-select-option>
  585. </a-select>
  586. <a-tag color="blue" v-if="initActionsData.deviceLabel" >{{initActionsData.deviceLabel}}</a-tag>
  587. <a-button
  588. type="primary"
  589. v-if="initActionsData.deviceType === 'target'"
  590. @click="openDeviceModal('actions')"
  591. >
  592. {{initActionsData.deviceId ? '重新选择' : '请选择设备'}}
  593. </a-button>
  594. </a-space>
  595. </a-form-item>
  596. <a-form-item label="告警名称" >
  597. <a-input v-model:value="initActionsData.warnLabel" ></a-input>
  598. </a-form-item>
  599. <a-form-item label="告警级别" >
  600. <a-select v-model:value="initActionsData.warnSeverity" >
  601. <a-select-option
  602. v-for='warnItem in warnSeverityList'
  603. :key="warnItem.key"
  604. :value="warnItem.key"
  605. >
  606. {{warnItem.name}}
  607. </a-select-option>
  608. </a-select>
  609. </a-form-item>
  610. </span>
  611. <span v-else-if="initActionsData.actionType === 'NOTICE'">
  612. <a-form-item label="提示名称" >
  613. <a-input v-model:value="initActionsData.noticeLabel" ></a-input>
  614. </a-form-item>
  615. <a-form-item label="提示描述" >
  616. <a-input v-model:value="initActionsData.noticeDescription" ></a-input>
  617. </a-form-item>
  618. <a-form-item label="提示用户" >
  619. <a-input v-model:value="initActionsData.userId" ></a-input>
  620. </a-form-item>
  621. </span>
  622. </a-form>
  623. </a-row>
  624. </div>
  625. </modal-pro>
  626. <modal-pro
  627. style="width: 700px"
  628. label="选择设备"
  629. :visible="state.deviceModalVisible"
  630. @cancel="state.deviceModalVisible = false"
  631. @ok="selectDevice"
  632. >
  633. <SelectDevice
  634. ref="selectDeviceRef"
  635. />
  636. </modal-pro>
  637. </template>
  638. <script lang='ts' setup >
  639. import { FormItemProps } from '@/components/FormPro/index.vue'
  640. import { ModelAttrController, ModelCmdController, ModelController, RuleController } from '@/controller'
  641. import { computed, nextTick, onMounted, reactive, ref, watch, getCurrentInstance } from 'vue'
  642. import { DownOutlined, FacebookFilled } from '@ant-design/icons-vue'
  643. import SelectDevice from './components/selectDevice.vue'
  644. import { useId } from '@/hooks'
  645. import { Form } from 'ant-design-vue'
  646. const {
  647. proxy: { $forceUpdate }
  648. }: any = getCurrentInstance()
  649. const useForm = Form.useForm
  650. const columns = [
  651. {
  652. title: '状态',
  653. dataIndex: 'status',
  654. key: 'status'
  655. },
  656. {
  657. title: '规则ID',
  658. dataIndex: 'id',
  659. key: 'id'
  660. },
  661. {
  662. title: '规则名称',
  663. dataIndex: 'ruleLabel',
  664. key: 'ruleLabel'
  665. },
  666. {
  667. title: '规则描述',
  668. dataIndex: 'ruleDescription',
  669. key: 'ruleDescription'
  670. },
  671. {
  672. title: '操作',
  673. dataIndex: 'action',
  674. key: 'action'
  675. }
  676. ]
  677. const formProps: FormItemProps[] = reactive([
  678. {
  679. label: '规则名称',
  680. key: 'ruleLabel',
  681. value: '',
  682. type: 'input',
  683. rules: true
  684. },
  685. {
  686. label: '规则描述',
  687. key: 'ruleDescription',
  688. value: '',
  689. type: 'textarea',
  690. rules: false
  691. }
  692. ])
  693. const conditionTypeList = [
  694. { key: 'DEVICE_DATA', name: '设备数据触发' },
  695. { key: 'DEVICE_SESSION', name: '设备状态触发' },
  696. { key: 'DAILY_TIMER', name: '周期时间条件' }
  697. ]
  698. const selectDeviceList = [
  699. { key: 'all', name: '全部设备' },
  700. { key: 'target', name: '指定设备' }
  701. ]
  702. const conditionColumns = reactive({
  703. DEVICE_DATA: [
  704. { title: '触发条件', dataIndex: 'conditionType' }, { title: '产品ID', dataIndex: 'modelId' },
  705. { title: '属性key', dataIndex: 'attributeKey' }, { title: '操作符', dataIndex: 'operator' },
  706. { title: '触发值', dataIndex: 'value' }, { title: '操作符', dataIndex: 'operator' }, { title: '操作', key: 'action' }
  707. ],
  708. DEVICE_SESSION: [
  709. { title: '触发条件', dataIndex: 'conditionType' }, { title: '产品ID', dataIndex: 'modelId' },
  710. { title: '设备类型', dataIndex: 'deviceType' }, { title: '设备名称', dataIndex: 'deviceLabel' },
  711. { title: 'sessionEventType', dataIndex: 'attributeKey', key: 'sessionEventType' }, { title: '操作', key: 'action' }
  712. ],
  713. DAILY_TIMER: [
  714. { title: '触发条件', dataIndex: 'conditionType' }, { title: '时间', dataIndex: 'time', key: 'time' },
  715. { title: '日期', dataIndex: 'dayOfWeek', key: 'dayOfWeek' }, { title: '操作', key: 'action' }
  716. ]
  717. })
  718. const actionsColumns = reactive({
  719. DEVICE_CMD: [
  720. { title: '触发动作', dataIndex: 'actionType' }, { title: '产品ID', dataIndex: 'modelId' },
  721. { title: '设备id', dataIndex: 'deviceId' }, { title: '命令名称', dataIndex: 'cmdLabel' },
  722. { title: '命令参数', dataIndex: 'cmdParameters' }, { title: '操作', dataIndex: 'action', key: 'action' }
  723. ],
  724. REPORT_WARN: [
  725. { title: '触发动作', dataIndex: 'actionType' }, { title: '设备id', dataIndex: 'deviceId' },
  726. { title: '告警名称', dataIndex: 'warnLabel' }, { title: '告警描述', dataIndex: 'warnDescription' },
  727. { title: '告警级别', dataIndex: 'warnSeverity' }, { title: '操作', dataIndex: 'action', key: 'action' }
  728. ],
  729. RESUME_WARN: [
  730. { title: '触发动作', dataIndex: 'actionType' }, { title: '告警名称', dataIndex: 'warnLabel' },
  731. { title: '告警级别', dataIndex: 'warnSeverity' }, { title: '操作', dataIndex: 'action', key: 'action' }
  732. ],
  733. NOTICE: [
  734. { title: '触发动作', dataIndex: 'actionType' }, { title: '提示名称', dataIndex: 'noticeLabel' },
  735. { title: '提示描述', dataIndex: 'noticeDescription' }, { title: '提示用户', dataIndex: 'userId' },
  736. { title: '操作', dataIndex: 'action', key: 'action' }
  737. ]
  738. })
  739. const sessionEventTypeList = [
  740. { key: 'CONNECT', name: '连接' },
  741. { key: 'DISCONNECT', name: '断开连接' }
  742. ]
  743. const dayOptions = [
  744. { value: 1, label: '周一' },
  745. { value: 2, label: '周二' },
  746. { value: 3, label: '周三' },
  747. { value: 4, label: '周四' },
  748. { value: 5, label: '周五' },
  749. { value: 6, label: '周六' },
  750. { value: 7, label: '周日' }
  751. ]
  752. const actionTypeList = [
  753. { key: 'DEVICE_CMD', name: '设备命令' },
  754. { key: 'REPORT_WARN', name: '上报告警' },
  755. { key: 'RESUME_WARN', name: '恢复告警' },
  756. { key: 'NOTICE', name: '通知' }
  757. ]
  758. const warnSeverityList = [
  759. { key: 'NOTICE', name: '提示' },
  760. { key: 'MINOR', name: '次要' },
  761. { key: 'MJAJOP', name: '重要' },
  762. { key: 'EMERGENCY', name: '紧急' }
  763. ]
  764. const operatorList = [
  765. 'EQ', 'NE', 'GT', 'GE', 'LT', 'LE', 'BETWEEN'
  766. ]
  767. const selectDeviceRef = ref('')
  768. const formProRef = ref('')
  769. const queryParamsState = reactive({
  770. page: 1,
  771. pageSize: 10,
  772. total: 0,
  773. ruleLabel: ''
  774. })
  775. const _initConditionsData = {
  776. conditionType: '',
  777. modelId: '',
  778. deviceType: '',
  779. deviceLabel: '',
  780. deviceId: '',
  781. sessionEventType: 'CONNECT',
  782. dayOfWeek: [],
  783. time: '',
  784. noticeLabel: '',
  785. noticeDescription: '',
  786. userId: '',
  787. attributeKey: '',
  788. operator: 'EQ',
  789. value: '',
  790. v1: '',
  791. v2: ''
  792. }
  793. const initConditionsData = reactive({ ..._initConditionsData })
  794. const _initActionsData = {
  795. actionType: '',
  796. modelId: '',
  797. deviceId: '',
  798. deviceLabel: '',
  799. deviceType: '',
  800. cmdId: '',
  801. cmdLabel: '',
  802. cmdParameters: [],
  803. warnLabel: '',
  804. warnDescription: '',
  805. warnSeverity: '',
  806. noticeLabel: '',
  807. noticeDescription: '',
  808. userId: ''
  809. }
  810. const initActionsData = reactive({ ..._initActionsData })
  811. const bodyParamsState = reactive<{
  812. id: string
  813. conditions: [],
  814. actions: [],
  815. conditionLogic: string
  816. ruleLabel: string
  817. ruleDescription: string
  818. }>({
  819. id: '',
  820. ruleLabel: '',
  821. ruleDescription: '',
  822. conditionLogic: 'AND',
  823. conditions: [],
  824. actions: []
  825. })
  826. const state = reactive({
  827. loading: false,
  828. dataSource: [],
  829. visible: false,
  830. formVisible: false,
  831. deviceModalVisible: false,
  832. opraState: 'add',
  833. modelList: [],
  834. cmdList: [],
  835. attrList: [],
  836. opraModel: '',
  837. opraIndex: 0, // 点击 条件 与 动作 时的下标
  838. opraKey: ''
  839. })
  840. watch(
  841. () => initConditionsData.conditionType,
  842. () => {
  843. Object.keys(initConditionsData).forEach(key => {
  844. if (key !== 'conditionType') {
  845. initConditionsData[key] = _initConditionsData[key]
  846. }
  847. })
  848. }
  849. )
  850. watch(
  851. () => initActionsData.actionType,
  852. () => {
  853. Object.keys(initActionsData).forEach(key => {
  854. if (key !== 'actionType') {
  855. initActionsData[key] = _initActionsData[key]
  856. }
  857. })
  858. }
  859. )
  860. watch(
  861. () => initConditionsData.modelId,
  862. () => {
  863. console.log('我触发吗')
  864. getAttrList()
  865. },
  866. {
  867. deep: true
  868. }
  869. )
  870. watch(
  871. () => initActionsData.modelId,
  872. () => {
  873. initActionsData.cmdParameters = []
  874. initActionsData.cmdLabel = ''
  875. initActionsData.cmdId = ''
  876. getCmdList()
  877. }
  878. )
  879. watch(
  880. () => initActionsData.cmdId,
  881. () => {
  882. const cmdDetail = state.cmdList.find(item => item.id === initActionsData.cmdId)!
  883. console.log('cmdDetail:', cmdDetail)
  884. initActionsData.cmdParameters = cmdDetail.cmdParams
  885. console.log(' initActionsData.cmdParameters:', initActionsData.cmdParameters, initActionsData.cmdId)
  886. initActionsData.cmdLabel = cmdDetail.cmdLabel
  887. }
  888. )
  889. const deviceSessionSource = computed(() => bodyParamsState.conditions.filter(item => item.conditionType === 'DEVICE_SESSION'))
  890. const deviceDataSource = computed(() => bodyParamsState.conditions.filter(item => item.conditionType === 'DEVICE_DATA'))
  891. const dailyTimerSource = computed(() => bodyParamsState.conditions.filter(item => item.conditionType === 'DAILY_TIMER'))
  892. const deviceCmdsource = computed(() => bodyParamsState.actions.filter(item => item.actionType === 'DEVICE_CMD'))
  893. const reportWarnSource = computed(() => bodyParamsState.actions.filter(item => item.actionType === 'REPORT_WARN'))
  894. const resumeWarnSource = computed(() => bodyParamsState.actions.filter(item => item.actionType === 'RESUME_WARN'))
  895. const noticeSource = computed(() => bodyParamsState.actions.filter(item => item.actionType === 'NOTICE'))
  896. const { resetFields, validate, validateInfos } = useForm(bodyParamsState, {
  897. ruleLabel: [{ required: true, message: '请填写联动规则名称' }]
  898. })
  899. const changeStatus = async (record) => RuleController.updateLinkStatus({ id: record.id, status: record.status })
  900. const changeConditionLogic = (record: string) => {
  901. bodyParamsState.conditionLogic = record
  902. }
  903. const openModal = (_opraState: 'add' | 'update' | 'preview', record: any) => {
  904. state.visible = true
  905. state.opraState = _opraState
  906. getLinkPageById(record.id)
  907. }
  908. const ok = async () => {
  909. validate().then(async () => {
  910. bodyParamsState.conditions.forEach(item => {
  911. if (item.operator === 'BETWEEN') {
  912. item.value = `{${item.v1}, ${item.v2}}`
  913. }
  914. })
  915. bodyParamsState.actions.forEach(item => {
  916. if (item.cmdParameters && item.cmdParameters.length) {
  917. const obj = {}
  918. item.cmdParameters.forEach(item => {
  919. obj[item.paramLabel] = item.dataUnit
  920. })
  921. item.cmdParameters = obj
  922. }
  923. })
  924. state.opraState === 'add' ? await RuleController.addLink({ ...bodyParamsState }) : await RuleController.updateLink({ ...bodyParamsState })
  925. state.visible = false
  926. getLinkPage()
  927. })
  928. }
  929. const delLinkRule = async (id: string) => {
  930. await RuleController.delLink(id)
  931. getLinkPage()
  932. }
  933. // 选择设备
  934. const selectDevice = () => {
  935. const _device = selectDeviceRef.value.getSelectDevice()
  936. state.deviceModalVisible = false
  937. if (state.opraKey === 'conditions') {
  938. initConditionsData.deviceLabel = _device.deviceLabelß
  939. initConditionsData.deviceId = _device.id
  940. } else {
  941. initActionsData.deviceLabel = _device.deviceLabel
  942. initActionsData.deviceId = _device.id
  943. }
  944. }
  945. const changePage = ({ current }) => {
  946. queryParamsState.page = current
  947. getLinkPage()
  948. }
  949. // 打开选择设备弹窗
  950. const openDeviceModal = (key: 'conditions' | 'actions') => {
  951. state.deviceModalVisible = true
  952. state.opraKey = key
  953. }
  954. const openFormVisible = (model: 'conditions' | 'actions') => {
  955. state.formVisible = true
  956. state.opraModel = model
  957. }
  958. // 删除条件或则动作
  959. const delCondiTionsAndActions = (id: string, key: 'conditions' | 'actions') => {
  960. const index = bodyParamsState[key].findIndex(item => item.id === id)
  961. bodyParamsState[key].splice(index, 1)
  962. }
  963. const selectConditionAndAction = () => {
  964. if (state.opraModel === 'conditions') {
  965. bodyParamsState.conditions.push({ ...initConditionsData, id: useId() })
  966. } else {
  967. bodyParamsState.actions.push({ ...initActionsData, id: useId() })
  968. }
  969. state.formVisible = false
  970. }
  971. // 获取命令
  972. const getCmdList = async () => {
  973. const { data } = await ModelCmdController.list({ modelId: initActionsData.modelId })
  974. state.cmdList = data
  975. }
  976. // 获取属性
  977. const getAttrList = async () => {
  978. const { data } = await ModelAttrController.list({ modelId: initConditionsData.modelId })
  979. state.attrList = data
  980. }
  981. // 获取模型
  982. const getModelList = async () => {
  983. const { data } = await ModelController.list()
  984. state.modelList = data
  985. }
  986. const getLinkPageById = async (id: string) => {
  987. const { data } = await RuleController.getLinkById(id)
  988. console.log(data)
  989. resetFields({
  990. ruleLabel: data.ruleLabel,
  991. ruleDescription: data.ruleDescription
  992. })
  993. bodyParamsState.conditionLogic = data.conditionLogic
  994. bodyParamsState.actions = data.actions.map(item => {
  995. return {
  996. ...item,
  997. id: useId()
  998. }
  999. })
  1000. bodyParamsState.conditions = data.conditions.map(item => {
  1001. return {
  1002. ...item,
  1003. id: useId()
  1004. }
  1005. })
  1006. $forceUpdate()
  1007. bodyParamsState.id = data.id
  1008. }
  1009. const getLinkPage = async () => {
  1010. state.loading = true
  1011. const { data, sum } = await RuleController.pageLink(queryParamsState)
  1012. state.dataSource = data
  1013. queryParamsState.total = sum
  1014. state.loading = false
  1015. }
  1016. onMounted(() => {
  1017. getLinkPage()
  1018. getModelList()
  1019. })
  1020. </script>
  1021. <style lang='less' scoped >
  1022. .content {
  1023. width: 100%;
  1024. height: 45px;
  1025. background-color: #F2F5FC;
  1026. display: flex;
  1027. justify-content: center;
  1028. align-items: center;
  1029. margin: 20px 0;
  1030. }
  1031. .df {
  1032. display: flex;
  1033. justify-content: end;
  1034. }
  1035. </style>