index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. <template>
  2. <div style="padding: 10px">
  3. <!-- 搜索栏 -->
  4. <div style="margin-bottom: 10px">
  5. <!-- 选择设备 -->
  6. <el-select
  7. v-model="selectedDeviceId"
  8. placeholder="选择设备"
  9. size="small"
  10. style="width: 150px"
  11. clearable
  12. >
  13. <el-option
  14. style="color: black"
  15. v-for="device in devices"
  16. :key="device.id"
  17. :label="device.name"
  18. :value="device.id"
  19. />
  20. </el-select>
  21. <el-button
  22. type="primary"
  23. @click="handleSearch()"
  24. style="margin-left: 10px"
  25. >点击输入查询条件进行查询</el-button
  26. >
  27. </div>
  28. <!-- 人员表格 -->
  29. <el-table
  30. v-loading="loading"
  31. :data="tableData"
  32. style="width: 100%; margin-top: 10px"
  33. border
  34. :header-cell-style="changeHeaderCellStyle"
  35. @selection-change="handleSelectionChange"
  36. >
  37. <el-table-column type="selection" align="center" width="50" />
  38. <el-table-column label="序号" align="center" min-width="50" sortable>
  39. <template #default="scope">
  40. {{ (currentPage - 1) * pageSize + scope.$index + 1 }}
  41. </template>
  42. </el-table-column>
  43. <el-table-column
  44. prop="employeeNo"
  45. label="序号"
  46. width="100"
  47. align="center"
  48. />
  49. <el-table-column
  50. prop="dwMajor"
  51. label="报警主类型"
  52. min-width="100"
  53. align="center"
  54. />
  55. <el-table-column
  56. prop="dwMinor"
  57. label="报警次类型"
  58. min-width="100"
  59. align="center"
  60. />
  61. <el-table-column
  62. prop="wInductiveEventType"
  63. label="归纳事件类型"
  64. min-width="100"
  65. align="center"
  66. >
  67. <template #default="{ row }">
  68. {{ (getInductiveEventName(row.wInductiveEventType), "access") }}
  69. </template>
  70. </el-table-column>
  71. <el-table-column
  72. prop="struTime"
  73. label="事件时间"
  74. min-width="200"
  75. align="center"
  76. >
  77. <template #default="{ row }">
  78. {{ formatNetDvrTime(row.struTime) }}
  79. </template>
  80. </el-table-column>
  81. <el-table-column
  82. prop="sNetUser"
  83. label="用户"
  84. min-width="100"
  85. align="center"
  86. />
  87. <el-table-column
  88. prop="struRemoteHostAddr"
  89. label="设备IP"
  90. min-width="100"
  91. align="center"
  92. />
  93. <el-table-column label="操作" fixed="right" width="100" align="center">
  94. <template slot-scope="scope">
  95. <el-button type="text" size="small" @click="viewFaceInfo(scope.row)"
  96. >查看</el-button
  97. >
  98. </template>
  99. </el-table-column>
  100. </el-table>
  101. <!-- 分页 -->
  102. <div style="margin-top: 10px; text-align: right">
  103. <el-pagination
  104. background
  105. layout="total, sizes, prev, pager, next, jumper"
  106. :total="total"
  107. :current-page.sync="currentPage"
  108. :page-size="pageSize"
  109. :page-sizes="[5, 10, 20, 50, 100]"
  110. @size-change="handleSizeChange"
  111. @current-change="handlePageChange"
  112. />
  113. </div>
  114. <!-- 搜索弹窗 -->
  115. <event-search-dialog
  116. :visible.sync="searchVisible"
  117. :event-data="currentEvent"
  118. @submit="handleEventSubmit"
  119. @cancel="handleEventCancel"
  120. />
  121. <!-- 查看详情弹窗 -->
  122. <event-detail-dialog
  123. :visible.sync="viewVisible"
  124. :event-data="currentEvent"
  125. />
  126. </div>
  127. </template>
  128. <script>
  129. import request from "@/utils/request";
  130. import EventSearchDialog from "./EventSearchDialog.vue";
  131. import EventDetailDialog from "./EventDetailDialog.vue";
  132. export default {
  133. name: "EventManage",
  134. components: {
  135. EventSearchDialog,
  136. EventDetailDialog,
  137. },
  138. data() {
  139. return {
  140. multipleSelection: [],
  141. currentEvent: null,
  142. loading: false,
  143. devices: [], // 设备列表
  144. selectedDeviceId: null, // 当前选择的设备
  145. tableData: [
  146. {
  147. dwMajor: 1,
  148. dwMinor: 2,
  149. wInductiveEventType: 3,
  150. struTime: {
  151. dwYear: 2025,
  152. dwMonth: 10,
  153. dwDay: 24,
  154. dwHour: 19,
  155. dwMinute: 30,
  156. dwSecond: 45,
  157. },
  158. sNetUser: "admin",
  159. struRemoteHostAddr: "192.168.1.100",
  160. },
  161. {
  162. dwMajor: 1,
  163. dwMinor: 5,
  164. wInductiveEventType: 1,
  165. struTime: {
  166. dwYear: 2025,
  167. dwMonth: 10,
  168. dwDay: 24,
  169. dwHour: 20,
  170. dwMinute: 15,
  171. dwSecond: 10,
  172. },
  173. sNetUser: "operator",
  174. struRemoteHostAddr: "192.168.1.101",
  175. },
  176. ],
  177. total: 0,
  178. currentPage: 1,
  179. pageSize: 10,
  180. searchVisible: false,
  181. viewVisible: false,
  182. };
  183. },
  184. mounted() {
  185. this.getDeviceNameInfo();
  186. },
  187. methods: {
  188. async handleEventSubmit(eventData) {
  189. console.log(eventData);
  190. // const url = deviceData.id ? "/device/update" : "/device/add";
  191. // const res = await request({ url, method: "POST", data: deviceData });
  192. this.searchVisible = false;
  193. // await this.$message(res.data);
  194. // await this.getDeviceInfo();
  195. },
  196. handleEventCancel() {
  197. this.searchVisible = false;
  198. },
  199. viewFaceInfo(row) {
  200. this.currentEvent = row;
  201. this.viewVisible = true;
  202. },
  203. formatNetDvrTime(time) {
  204. if (!time) return "-";
  205. const { dwYear, dwMonth, dwDay, dwHour, dwMinute, dwSecond } = time;
  206. return (
  207. `${dwYear}-${String(dwMonth).padStart(2, "0")}-${String(dwDay).padStart(2, "0")} ` +
  208. `${String(dwHour).padStart(2, "0")}:${String(dwMinute).padStart(2, "0")}:${String(dwSecond).padStart(2, "0")}`
  209. );
  210. },
  211. getInductiveEventName(type, deviceType = "access") {
  212. const maps = {
  213. // 1️⃣ HIKVISION 门禁主机
  214. access: {
  215. 0: "无效",
  216. 1: "认证通过",
  217. 2: "认证失败",
  218. 3: "开门动作",
  219. 4: "关门动作",
  220. 5: "门异常",
  221. 6: "远程操作",
  222. 7: "校时事件",
  223. 8: "设备异常事件",
  224. 9: "设备恢复正常事件",
  225. 10: "报警事件",
  226. 11: "报警恢复事件",
  227. 12: "呼叫中心",
  228. },
  229. // 2️⃣ HIKVISION 可视对讲
  230. intercom: {
  231. 1: "防拆报警",
  232. 2: "劫持报警",
  233. 3: "多次密码开锁失败报警",
  234. 4: "门未开报警",
  235. 5: "门未关报警",
  236. 6: "通话对讲报警",
  237. 7: "密码开锁",
  238. 8: "劫持开锁",
  239. 9: "刷卡开锁",
  240. 10: "户主开锁",
  241. 11: "中心平台开锁",
  242. 12: "设备对讲",
  243. },
  244. // 3️⃣ HIKVISION 报警主机
  245. alarm: {
  246. 1: "防区事件",
  247. 2: "主机事件",
  248. },
  249. // 4️⃣ 第三方 GJD 报警主机
  250. gjd: {
  251. 1: "对象侦测报警",
  252. 2: "人为防拆报警",
  253. 3: "弱光检测报警",
  254. 4: "定时报警(周期性)",
  255. 5: "温度检测报警",
  256. },
  257. // 5️⃣ 第三方 Luminite 报警主机
  258. luminite: {
  259. 1: "探测到移动",
  260. 2: "传感器被干扰",
  261. 3: "信号被遮挡",
  262. 4: "检测到震动",
  263. 5: "传感器故障",
  264. 6: "传感器位置移动",
  265. 7: "电池不足",
  266. 8: "手动冲突数据",
  267. 9: "接收机收到干扰信息",
  268. 10: "防拆弹簧松弛",
  269. },
  270. // 6️⃣ 第三方 OPTEX 报警主机
  271. optex: {
  272. 1: "远&近发生事件",
  273. 2: "远距离事件",
  274. 3: "近距离事件",
  275. 4: "缓慢移动检测",
  276. 5: "干扰检测",
  277. 6: "防遮挡报警",
  278. 7: "防旋转报警",
  279. 8: "异常电路激活",
  280. 9: "污物覆盖(自检异常)",
  281. 10: "传感器异常",
  282. 11: "设备故障",
  283. 12: "设备不在线",
  284. 13: "设备已连接",
  285. 14: "区域A1事件",
  286. 15: "区域A2事件",
  287. 16: "区域B1事件",
  288. 17: "区域B2事件",
  289. 18: "区域A11事件",
  290. 19: "区域A12事件",
  291. 20: "区域A21事件",
  292. 21: "区域A22事件",
  293. 22: "区域B11事件",
  294. 23: "区域B12事件",
  295. 24: "区域B21事件",
  296. 25: "区域B22事件",
  297. },
  298. };
  299. // 防御性处理
  300. if (!type) return "无效";
  301. const map = maps[deviceType] || maps.access;
  302. return map[type] || `未知(${type})`;
  303. },
  304. handleSearch() {
  305. console.log("查询");
  306. this.currentEvent = {};
  307. this.searchVisible = true;
  308. },
  309. // 表格样式修改
  310. changeHeaderCellStyle(row, column, rowIndex, columnIndex) {
  311. if (row.columnIndex === 0) {
  312. return "background: #004279 ; color:#fff;"; // 修改的样式
  313. } else {
  314. return "background: #004279 ;color:#fff; ";
  315. }
  316. },
  317. // 监听多选变化
  318. handleSelectionChange(val) {
  319. this.multipleSelection = val;
  320. },
  321. // 切换页码
  322. handlePageChange(page) {
  323. this.currentPage = page;
  324. // this.searchUserInfo()
  325. },
  326. // 修改每页条数
  327. handleSizeChange(size) {
  328. this.pageSize = size;
  329. this.currentPage = 1; // 切换条数后回到第一页
  330. // this.searchUserInfo()
  331. },
  332. async getDeviceNameInfo() {
  333. try {
  334. this.loading = true;
  335. const res = await request({
  336. url: "/device/listDeviceName",
  337. method: "GET",
  338. });
  339. // 判断返回结构
  340. if (res && res.list) {
  341. this.devices = res.list;
  342. this.total = res.total || 0;
  343. console.log("设备列表:", this.devices);
  344. if (this.devices.length > 0) {
  345. this.selectedDeviceId = this.devices[0].id;
  346. console.log("选中的设备ID:", this.selectedDeviceId);
  347. // 获取该设备的人员信息
  348. // this.searchUserInfo()
  349. }
  350. } else {
  351. this.devices = [];
  352. this.total = 0;
  353. this.$message.warning("未获取到设备数据");
  354. }
  355. } catch (error) {
  356. console.error("获取设备信息失败:", error);
  357. this.$message.error("获取设备列表失败,请检查网络或后端接口!");
  358. } finally {
  359. this.loading = false;
  360. }
  361. },
  362. },
  363. };
  364. </script>
  365. <style scoped>
  366. .car-event-page {
  367. display: flex;
  368. padding: 10px;
  369. }
  370. .query-panel {
  371. width: 280px;
  372. padding: 10px;
  373. border-right: 1px solid #ddd;
  374. }
  375. .table-panel {
  376. flex: 1;
  377. padding: 10px;
  378. }
  379. .quick-btns {
  380. display: flex;
  381. gap: 6px;
  382. margin: 6px 0;
  383. }
  384. .pagination {
  385. margin-top: 10px;
  386. text-align: right;
  387. }
  388. </style>