index.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. <template>
  2. <ContentWrap>
  3. <!-- 搜索工作栏 -->
  4. <el-form
  5. class="-mb-15px"
  6. :model="queryParams"
  7. ref="queryFormRef"
  8. :inline="true"
  9. label-width="68px"
  10. >
  11. <el-form-item label="告警配置" prop="configId">
  12. <el-select
  13. v-model="queryParams.configId"
  14. placeholder="请选择告警配置"
  15. clearable
  16. filterable
  17. class="!w-240px"
  18. >
  19. <el-option
  20. v-for="config in alertConfigList"
  21. :key="config.id"
  22. :label="config.name"
  23. :value="config.id"
  24. />
  25. </el-select>
  26. </el-form-item>
  27. <el-form-item label="告警级别" prop="configLevel">
  28. <el-select
  29. v-model="queryParams.configLevel"
  30. placeholder="请选择告警级别"
  31. clearable
  32. class="!w-240px"
  33. >
  34. <el-option
  35. v-for="dict in getIntDictOptions(DICT_TYPE.IOT_ALERT_LEVEL)"
  36. :key="dict.value"
  37. :label="dict.label"
  38. :value="dict.value"
  39. />
  40. </el-select>
  41. </el-form-item>
  42. <el-form-item label="产品" prop="productId">
  43. <el-select
  44. v-model="queryParams.productId"
  45. placeholder="请选择产品"
  46. clearable
  47. filterable
  48. @change="handleProductChange"
  49. class="!w-240px"
  50. >
  51. <el-option
  52. v-for="product in productList"
  53. :key="product.id"
  54. :label="product.name"
  55. :value="product.id"
  56. />
  57. </el-select>
  58. </el-form-item>
  59. <el-form-item label="设备" prop="deviceId">
  60. <el-select
  61. v-model="queryParams.deviceId"
  62. placeholder="请选择设备"
  63. clearable
  64. filterable
  65. class="!w-240px"
  66. >
  67. <el-option
  68. v-for="device in filteredDeviceList"
  69. :key="device.id"
  70. :label="device.deviceName"
  71. :value="device.id"
  72. />
  73. </el-select>
  74. </el-form-item>
  75. <el-form-item label="是否处理" prop="processStatus">
  76. <el-select
  77. v-model="queryParams.processStatus"
  78. placeholder="请选择是否处理"
  79. clearable
  80. class="!w-240px"
  81. >
  82. <el-option
  83. v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
  84. :key="String(dict.value)"
  85. :label="dict.label"
  86. :value="dict.value"
  87. />
  88. </el-select>
  89. </el-form-item>
  90. <el-form-item label="创建时间" prop="createTime">
  91. <el-date-picker
  92. v-model="queryParams.createTime"
  93. value-format="YYYY-MM-DD HH:mm:ss"
  94. type="daterange"
  95. start-placeholder="开始日期"
  96. end-placeholder="结束日期"
  97. :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
  98. class="!w-220px"
  99. />
  100. </el-form-item>
  101. <el-form-item>
  102. <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
  103. <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
  104. </el-form-item>
  105. </el-form>
  106. </ContentWrap>
  107. <!-- 列表 -->
  108. <ContentWrap>
  109. <el-table
  110. row-key="id"
  111. v-loading="loading"
  112. :data="list"
  113. :stripe="true"
  114. :show-overflow-tooltip="true"
  115. >
  116. <el-table-column label="记录编号" align="center" prop="id" />
  117. <el-table-column label="告警名称" align="center" prop="configName" />
  118. <el-table-column label="告警级别" align="center" prop="configLevel">
  119. <template #default="scope">
  120. <dict-tag :type="DICT_TYPE.IOT_ALERT_LEVEL" :value="scope.row.configLevel" />
  121. </template>
  122. </el-table-column>
  123. <el-table-column label="产品名称" align="center" prop="productId">
  124. <template #default="scope">
  125. {{ getProductName(scope.row.productId) }}
  126. </template>
  127. </el-table-column>
  128. <el-table-column label="设备名称" align="center" prop="deviceId">
  129. <template #default="scope">
  130. {{ getDeviceName(scope.row.deviceId) }}
  131. </template>
  132. </el-table-column>
  133. <el-table-column label="触发的设备消息" align="center" prop="deviceMessage">
  134. <template #default="scope">
  135. <el-popover
  136. placement="top-start"
  137. :width="600"
  138. trigger="hover"
  139. v-if="scope.row.deviceMessage"
  140. >
  141. <template #reference>
  142. <el-button link type="primary">
  143. <Icon icon="ep:view" class="mr-5px" />
  144. 查看消息
  145. </el-button>
  146. </template>
  147. <pre>{{ scope.row.deviceMessage }}</pre>
  148. </el-popover>
  149. <span v-else class="text-gray-400">-</span>
  150. </template>
  151. </el-table-column>
  152. <el-table-column label="是否处理" align="center" prop="processStatus">
  153. <template #default="scope">
  154. <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.processStatus" />
  155. </template>
  156. </el-table-column>
  157. <el-table-column label="处理结果" align="center" prop="processRemark" />
  158. <el-table-column
  159. label="创建时间"
  160. align="center"
  161. prop="createTime"
  162. :formatter="dateFormatter"
  163. width="180px"
  164. />
  165. <el-table-column label="操作" align="center" min-width="120px">
  166. <template #default="scope">
  167. <el-button
  168. v-if="!scope.row.processStatus"
  169. link
  170. type="primary"
  171. @click="handleProcess(scope.row)"
  172. v-hasPermi="['iot:alert-record:process']"
  173. >
  174. 处理
  175. </el-button>
  176. </template>
  177. </el-table-column>
  178. </el-table>
  179. <!-- 分页 -->
  180. <Pagination
  181. :total="total"
  182. v-model:page="queryParams.pageNo"
  183. v-model:limit="queryParams.pageSize"
  184. @pagination="getList"
  185. />
  186. </ContentWrap>
  187. </template>
  188. <script setup lang="ts">
  189. import { dateFormatter } from '@/utils/formatTime'
  190. import { AlertRecordApi, AlertRecord } from '@/api/iot/alert/record'
  191. import { AlertConfigApi, AlertConfig } from '@/api/iot/alert/config'
  192. import { ProductApi, ProductVO } from '@/api/iot/product/product'
  193. import { DeviceApi, DeviceVO } from '@/api/iot/device/device'
  194. import { DICT_TYPE, getIntDictOptions, getBoolDictOptions } from '@/utils/dict'
  195. /** IoT 告警记录列表 */
  196. defineOptions({ name: 'IotAlertRecord' })
  197. const message = useMessage() // 消息弹窗
  198. const loading = ref(true) // 列表的加载中
  199. const list = ref<AlertRecord[]>([]) // 列表的数据
  200. const total = ref(0) // 列表的总页数
  201. const alertConfigList = ref<AlertConfig[]>([]) // 告警配置列表
  202. const productList = ref<ProductVO[]>([]) // 产品列表
  203. const deviceList = ref<DeviceVO[]>([]) // 设备列表
  204. const queryParams = reactive({
  205. pageNo: 1,
  206. pageSize: 10,
  207. configId: undefined as number | undefined,
  208. configLevel: undefined as number | undefined,
  209. productId: undefined as number | undefined,
  210. deviceId: undefined as number | undefined,
  211. processStatus: undefined as boolean | undefined,
  212. createTime: [] as string[]
  213. })
  214. const queryFormRef = ref() // 搜索的表单
  215. /** 根据选择的产品 ID,筛选设备列表 */
  216. const filteredDeviceList = computed(() => {
  217. if (!queryParams.productId) {
  218. return deviceList.value
  219. }
  220. return deviceList.value.filter((device) => device.productId === queryParams.productId)
  221. })
  222. /** 根据产品 ID 获取产品名称 */
  223. const getProductName = (productId: number) => {
  224. if (!productId) {
  225. return `-`
  226. }
  227. const product = productList.value.find((p) => p.id === productId)
  228. return product ? product.name : `加载中...`
  229. }
  230. /** 根据设备 ID 获取设备名称 */
  231. const getDeviceName = (deviceId: number) => {
  232. if (!deviceId) {
  233. return `-`
  234. }
  235. const device = deviceList.value.find((d) => d.id === deviceId)
  236. return device ? device.deviceName : `加载中...`
  237. }
  238. /** 查询列表 */
  239. const getList = async () => {
  240. loading.value = true
  241. try {
  242. const data = await AlertRecordApi.getAlertRecordPage(queryParams)
  243. list.value = data.list
  244. total.value = data.total
  245. } finally {
  246. loading.value = false
  247. }
  248. }
  249. /** 搜索按钮操作 */
  250. const handleQuery = () => {
  251. queryParams.pageNo = 1
  252. getList()
  253. }
  254. /** 重置按钮操作 */
  255. const resetQuery = () => {
  256. queryFormRef.value.resetFields()
  257. handleQuery()
  258. }
  259. /** 产品变更处理 */
  260. const handleProductChange = () => {
  261. queryParams.deviceId = undefined // 清空设备选择
  262. }
  263. /** 处理告警记录 */
  264. const handleProcess = async (row: AlertRecord) => {
  265. try {
  266. const { value: processRemark } = await ElMessageBox.prompt('请输入处理原因', '处理告警记录', {
  267. confirmButtonText: '确定',
  268. cancelButtonText: '取消'
  269. })
  270. await AlertRecordApi.processAlertRecord(row.id, processRemark)
  271. message.success('处理成功')
  272. await getList()
  273. } catch (error) {}
  274. }
  275. /** 初始化 **/
  276. onMounted(async () => {
  277. await getList()
  278. alertConfigList.value = await AlertConfigApi.getSimpleAlertConfigList()
  279. productList.value = await ProductApi.getSimpleProductList()
  280. deviceList.value = await DeviceApi.getSimpleDeviceList()
  281. })
  282. </script>