alarm-record.vue 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. <template>
  2. <div class="alarm-record-page">
  3. <!-- 搜索栏 -->
  4. <div class="search-bar">
  5. <div class="search-item">
  6. <span class="label">设备名称</span>
  7. <el-select
  8. v-model="form.deviceIp"
  9. clearable
  10. placeholder="请选择"
  11. size="small"
  12. >
  13. <el-option
  14. v-for="item in deviceList"
  15. :key="item.id"
  16. :label="item.name"
  17. :value="item.configIp"
  18. />
  19. </el-select>
  20. </div>
  21. <!-- <div class="search-item">
  22. <span class="label">告警规则</span>
  23. <el-select v-model="form.ruleId" clearable placeholder="请选择" size="small">
  24. <el-option
  25. v-for="item in ruleList"
  26. :key="item.id"
  27. :label="item.ruleName"
  28. :value="item.id"
  29. />
  30. </el-select>
  31. </div> -->
  32. <div class="search-item">
  33. <span class="label">告警时间</span>
  34. <el-date-picker
  35. v-model="form.timeList"
  36. type="datetimerange"
  37. size="small"
  38. start-placeholder="开始日期"
  39. end-placeholder="结束日期"
  40. range-separator="至"
  41. value-format="yyyy-MM-dd HH:mm:ss"
  42. @change="changeTime"
  43. />
  44. </div>
  45. <el-button
  46. type="primary"
  47. size="small"
  48. icon="el-icon-search"
  49. @click="serachClick"
  50. >搜索</el-button
  51. >
  52. </div>
  53. <!-- 视频网格 -->
  54. <div
  55. class="video-grid"
  56. v-loading="loading"
  57. element-loading-background="rgba(0, 0, 0, 0.8)"
  58. >
  59. <div
  60. class="video-card"
  61. v-for="(item, index) in videoList"
  62. :key="index"
  63. @click="openVideo(item)"
  64. >
  65. <div class="video-player">
  66. <img
  67. v-if="item.alarmImagePath"
  68. :src="setFileUrl(item.alarmImagePath)"
  69. alt=""
  70. />
  71. <div class="play-btn">
  72. <i class="el-icon-caret-right"></i>
  73. </div>
  74. </div>
  75. <div class="video-meta">
  76. <span class="device-name">{{ item.basicDeviceName }}</span>
  77. <span class="rule-name">{{ item.alarmType }}</span>
  78. <span class="alarm-time">{{ item.alarmTime }}</span>
  79. </div>
  80. </div>
  81. </div>
  82. <!-- 分页 -->
  83. <div class="pagination-bar">
  84. <el-pagination
  85. background
  86. layout="total, prev, pager, next, jumper"
  87. :current-page="pages.pageNum"
  88. :page-size="pages.pageSize"
  89. :total="pages.total"
  90. @current-change="current_change"
  91. />
  92. </div>
  93. <DialogVideo ref="DialogVideo" :width="'740px'"></DialogVideo>
  94. </div>
  95. </template>
  96. <script>
  97. import { recordList } from '@/api/surveillance/monitor';
  98. import DialogVideo from './components/DialogVideo.vue';
  99. import * as realTime from '@/api/isp/ispRealtime/monitor/index';
  100. export default {
  101. components: {
  102. DialogVideo
  103. },
  104. data() {
  105. return {
  106. ruleList: [],
  107. deviceList: [],
  108. pages: {
  109. pageNum: 1,
  110. pageSize: 12,
  111. total: 0
  112. },
  113. loading: false,
  114. videoList: [],
  115. form: {
  116. deviceIp: '',
  117. ruleId: '',
  118. timeList: null
  119. }
  120. };
  121. },
  122. created() {
  123. this.getData();
  124. realTime.listByType().then((res) => {
  125. this.deviceList = res;
  126. });
  127. },
  128. methods: {
  129. changeTime(e) {
  130. if (e) {
  131. this.beginDate = e[0];
  132. this.endDate = e[1];
  133. }
  134. },
  135. serachClick() {
  136. this.pages.pageNum = 1;
  137. this.getData();
  138. },
  139. setFileUrl(fileUrl) {
  140. let fileNames = fileUrl.split('/');
  141. return (
  142. window.location.origin +
  143. '/api/main/file/getFile?objectName=' +
  144. fileUrl +
  145. '&fullfilename=' +
  146. fileNames[fileNames.length - 1]
  147. );
  148. // return (
  149. // 'http://aiot.zoomwin.com.cn:51001/api/main/file/getFile?objectName=' +
  150. // fileUrl +
  151. // '&fullfilename=' +
  152. // fileNames[fileNames.length - 1]
  153. // );
  154. },
  155. getData() {
  156. let alarmTimeStart = this.form.timeList ? this.form.timeList[0] : null;
  157. let alarmTimeEnd = this.form.timeList ? this.form.timeList[1] : null;
  158. let params = {
  159. pageNum: this.pages.pageNum,
  160. pageSize: this.pages.pageSize,
  161. alarmTimeStart: alarmTimeStart,
  162. alarmTimeEnd: alarmTimeEnd,
  163. deviceIp: this.form.deviceIp
  164. };
  165. this.loading = true;
  166. recordList(params)
  167. .then((res) => {
  168. this.pages.pageNum = res.current;
  169. this.pages.total = res.total;
  170. this.videoList = res.records || [];
  171. })
  172. .finally(() => {
  173. this.loading = false;
  174. });
  175. },
  176. openVideo(val) {
  177. let url = val.recordVideoPath;
  178. this.$refs.DialogVideo.init(
  179. window.location.origin + '/kd-aiot' + url,
  180. ''
  181. );
  182. // this.$refs.DialogVideo.init(
  183. // 'http://aiot.zoomwin.com.cn:51001/kd-aiot' + url,
  184. // ''
  185. // );
  186. },
  187. current_change(val) {
  188. this.pages.pageNum = val;
  189. this.getData();
  190. }
  191. }
  192. };
  193. </script>
  194. <style lang="scss" scoped>
  195. .alarm-record-page {
  196. height: calc(100vh - 86px);
  197. background-color: #0d1b2a;
  198. padding: 15px;
  199. display: flex;
  200. flex-direction: column;
  201. box-sizing: border-box;
  202. .search-bar {
  203. display: flex;
  204. align-items: center;
  205. gap: 20px;
  206. margin-bottom: 15px;
  207. flex-shrink: 0;
  208. .search-item {
  209. display: flex;
  210. align-items: center;
  211. gap: 8px;
  212. .label {
  213. color: #b0c4de;
  214. font-size: 13px;
  215. white-space: nowrap;
  216. }
  217. ::v-deep .el-input__inner,
  218. ::v-deep .el-range-input {
  219. background-color: #1a2b3c;
  220. border-color: #2a3b4c;
  221. color: #fff;
  222. }
  223. ::v-deep .el-range-separator {
  224. color: #b0c4de;
  225. }
  226. ::v-deep .el-input__icon {
  227. color: #b0c4de;
  228. }
  229. }
  230. ::v-deep .el-button--primary {
  231. background-color: #1a6bc9;
  232. border-color: #1a6bc9;
  233. &:hover {
  234. background-color: #2580e0;
  235. border-color: #2580e0;
  236. }
  237. }
  238. }
  239. .video-grid {
  240. flex: 1;
  241. display: grid;
  242. grid-template-columns: repeat(4, 1fr);
  243. grid-template-rows: repeat(3, 1fr);
  244. gap: 12px;
  245. overflow-y: auto;
  246. &::-webkit-scrollbar {
  247. width: 6px;
  248. }
  249. &::-webkit-scrollbar-thumb {
  250. border-radius: 3px;
  251. background: #1a6bc9;
  252. }
  253. &::-webkit-scrollbar-track {
  254. border-radius: 3px;
  255. background: rgba(26, 107, 201, 0.2);
  256. }
  257. .video-card {
  258. background-color: #000;
  259. border-radius: 4px;
  260. overflow: hidden;
  261. cursor: pointer;
  262. display: flex;
  263. flex-direction: column;
  264. border: 1px solid #1a2b3c;
  265. transition: border-color 0.2s;
  266. &:hover {
  267. border-color: #1a6bc9;
  268. }
  269. .video-player {
  270. flex: 1;
  271. position: relative;
  272. background-color: #000;
  273. display: flex;
  274. align-items: center;
  275. justify-content: center;
  276. min-height: 0;
  277. img {
  278. width: 100%;
  279. height: 100%;
  280. object-fit: cover;
  281. }
  282. .play-btn {
  283. position: absolute;
  284. top: 50%;
  285. left: 50%;
  286. transform: translate(-50%, -50%);
  287. width: 50px;
  288. height: 50px;
  289. background-color: rgba(0, 0, 0, 0.6);
  290. border-radius: 50%;
  291. display: flex;
  292. align-items: center;
  293. justify-content: center;
  294. i {
  295. color: #fff;
  296. font-size: 28px;
  297. margin-left: 4px;
  298. }
  299. }
  300. }
  301. .video-meta {
  302. height: 28px;
  303. display: flex;
  304. align-items: center;
  305. gap: 10px;
  306. padding: 0 10px;
  307. background-color: #0a1626;
  308. flex-shrink: 0;
  309. overflow: hidden;
  310. span {
  311. font-size: 12px;
  312. white-space: nowrap;
  313. }
  314. .device-name {
  315. color: #b0c4de;
  316. }
  317. .rule-name {
  318. color: #8899aa;
  319. }
  320. .alarm-time {
  321. color: #8899aa;
  322. margin-left: auto;
  323. }
  324. }
  325. }
  326. }
  327. .pagination-bar {
  328. flex-shrink: 0;
  329. display: flex;
  330. justify-content: center;
  331. padding-top: 15px;
  332. ::v-deep .el-pagination {
  333. .el-pagination__total {
  334. color: #b0c4de;
  335. }
  336. .el-pagination__jump {
  337. color: #b0c4de;
  338. }
  339. .el-input__inner {
  340. background-color: #1a2b3c;
  341. border-color: #2a3b4c;
  342. color: #fff;
  343. }
  344. .btn-prev,
  345. .btn-next {
  346. background-color: #1a2b3c;
  347. color: #b0c4de;
  348. }
  349. .el-pager li {
  350. background-color: #1a2b3c;
  351. color: #b0c4de;
  352. &.active {
  353. background-color: #1a6bc9;
  354. color: #fff;
  355. }
  356. &:hover {
  357. color: #fff;
  358. }
  359. }
  360. }
  361. }
  362. }
  363. </style>