index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. <template>
  2. <div class="app-container">
  3. <el-form :model="query" ref="query" :inline="true" >
  4. <el-form-item label="设备id:" >
  5. <el-input
  6. v-model="query.deviceId"
  7. placeholder="请输入设备id"
  8. clearable
  9. ></el-input>
  10. </el-form-item>
  11. <el-form-item label="通道id:" >
  12. <el-input
  13. v-model="query.id"
  14. placeholder="请输入通道id"
  15. clearable
  16. ></el-input>
  17. </el-form-item>
  18. <el-form-item label="通道名称:" >
  19. <el-input
  20. v-model="query.name"
  21. placeholder="请输入通道名称"
  22. clearable
  23. ></el-input>
  24. </el-form-item>
  25. <el-form-item label="通道状态:" >
  26. <el-select
  27. v-model="query.status"
  28. placeholder="请选择通道状态"
  29. clearable
  30. size="small"
  31. style="width: 150px"
  32. >
  33. <el-option
  34. v-for="dict in statusOptions"
  35. :key="dict.dictValue"
  36. :label="dict.dictLabel"
  37. :value="dict.dictValue"
  38. />
  39. </el-select>
  40. </el-form-item>
  41. <el-form-item label="通道类型:" >
  42. <el-select
  43. v-model="query.cameraType"
  44. placeholder="请选择通道类型"
  45. clearable
  46. size="small"
  47. style="width: 150px"
  48. >
  49. <el-option
  50. v-for="dict in cameraTypeOptions"
  51. :key="dict.dictValue"
  52. :label="dict.dictLabel"
  53. :value="dict.dictValue"
  54. />
  55. </el-select>
  56. </el-form-item>
  57. <el-form-item class="right">
  58. <el-button plain size="mini" @click="resetQuery">重置</el-button>
  59. <el-button
  60. type="primary"
  61. size="mini"
  62. @click="getData()"
  63. >搜索</el-button
  64. >
  65. </el-form-item>
  66. <br>
  67. <el-button
  68. type="primary"
  69. size="mini"
  70. @click="getDhDeviceListNew()"
  71. >同步摄像头信息</el-button
  72. >
  73. <el-button
  74. type="primary"
  75. size="mini"
  76. @click="handleExport"
  77. >导出</el-button>
  78. </el-form>
  79. <!-- <el-divider></el-divider> -->
  80. <div ref="table">
  81. <el-table
  82. :data="tableData"
  83. row-key="id"
  84. :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
  85. v-loading="loading"
  86. border
  87. style="margin-top:20px"
  88. >
  89. <el-table-column prop="{deviceName}" label="硬盘录像机地址" show-overflow-tooltip>
  90. <template slot-scope="scope">
  91. {{scope.row.deviceName}}
  92. </template>
  93. </el-table-column>
  94. <el-table-column prop="deviceId" label="设备Id" show-overflow-tooltip></el-table-column>
  95. <el-table-column prop="id" label="通道Id" show-overflow-tooltip></el-table-column>
  96. <el-table-column prop="name" label="通道名称" show-overflow-tooltip></el-table-column>
  97. <!-- <el-table-column prop="status" label="状态" show-overflow-tooltip>
  98. <template slot-scope="scope">
  99. {{scope.row.status == "0" ? "未知" : scope.row.status == "1" ? "在线" : scope.row.status == "2" ? "离线" : ""}}
  100. </template>
  101. </el-table-column> -->
  102. <el-table-column prop="type" label="设备类型" show-overflow-tooltip>
  103. <template slot-scope="scope">
  104. {{
  105. scope.row.type == "1" ? "编码单元" : scope.row.type == "2" ? "解码单元" :
  106. scope.row.type == "3" ? "报警输入单元" : scope.row.type == "4" ? "报警输出单元" :
  107. scope.row.type == "5" ? "电视墙输入单元" : scope.row.type == "6" ? "电视墙输出单元" :
  108. scope.row.type == "7" ? "门禁单元" : scope.row.type == "8" ? "对讲单元" :
  109. scope.row.type == "10" ? "动环单元" : scope.row.type == "14" ? "闸道单元" :
  110. scope.row.type == "15" ? "LED 单元" : scope.row.type == "16" ? "周界单元" : ""
  111. }}
  112. </template>
  113. </el-table-column>
  114. <el-table-column prop="manufacturer" label="品牌" show-overflow-tooltip>
  115. <template slot-scope="scope">
  116. {{scope.row.manufacturer == "0" ? "未知" : scope.row.manufacturer == "1" ? "大华" :scope.row.manufacturer == "2" ? "海康" : ""}}
  117. </template>
  118. </el-table-column>
  119. <el-table-column prop="cameraType" label="通道类型" show-overflow-tooltip>
  120. <template slot-scope="scope">
  121. {{scope.row.cameraType == "1" ? "枪机" : scope.row.cameraType == "2" ? "球机"
  122. : scope.row.cameraType == "3" ? "半球" : scope.row.cameraType == "4" ? "证据通道" :""}}
  123. </template>
  124. </el-table-column>
  125. <!-- <el-table-column prop="longitude" label="经度" show-overflow-tooltip></el-table-column>
  126. <el-table-column prop="latitude" label="维度" show-overflow-tooltip></el-table-column>
  127. <el-table-column prop="address" label="安装位置" show-overflow-tooltip></el-table-column> -->
  128. <el-table-column label="操作" width="190" fixed="right">
  129. <template slot-scope="scope">
  130. <el-button
  131. class="lans"
  132. plain
  133. @click="play(scope.row)"
  134. >播放</el-button
  135. >
  136. <el-button
  137. class="lans"
  138. plain
  139. @click="Hplay(scope.row)"
  140. >回放</el-button
  141. >
  142. </template>
  143. </el-table-column>
  144. </el-table>
  145. </div>
  146. <el-pagination
  147. background
  148. @current-change="handleCurrentChange"
  149. :page-sizes="[10, 15, 20, 30]"
  150. @size-change="handleSizeChange"
  151. :current-page="query.pageNo"
  152. :page-size="query.pageSize"
  153. layout="sizes,prev, pager, next"
  154. :total="totalCount"
  155. >
  156. </el-pagination>
  157. <el-dialog title="回放时间选择" :visible.sync="dialogFormVisible3" width="600">
  158. <div class="block">
  159. <el-date-picker
  160. @change="dateData"
  161. value-format="yyyy-MM-dd HH:mm:ss"
  162. v-model="value"
  163. range-separator
  164. type="datetimerange"
  165. align="center"
  166. start-placeholder="开始日期"
  167. end-placeholder="结束日期"
  168. class="picker"
  169. :default-time="['00:00:00', '23:59:59']">
  170. </el-date-picker>
  171. <el-button
  172. v-if="dateDataJlStatus"
  173. size="small"
  174. type="primary"
  175. class="search-button pickerBut"
  176. @click="dateDataJl" >确定</el-button>
  177. </div>
  178. </el-dialog>
  179. <!-- 本地注册 -->
  180. <el-dialog :title="title" :visible.sync="dialogFormVisible">
  181. <el-form v-for="(from, index) in from_data" :key="index">
  182. <el-form-item
  183. :label="from.label"
  184. :label-width="formLabelWidth"
  185. v-if="from.bool == true"
  186. >
  187. <el-select
  188. @change="select_Value(index)"
  189. v-model="from.value"
  190. placeholder="请选择"
  191. style="width: 220px"
  192. >
  193. <el-option
  194. v-for="item in from.array"
  195. :key="item.value"
  196. :label="item.label"
  197. :value="item.value"
  198. >
  199. </el-option>
  200. </el-select>
  201. </el-form-item>
  202. </el-form>
  203. <div slot="footer" class="dialog-footer">
  204. <el-button
  205. @click="dialogFormVisible = false"
  206. plain
  207. >取 消</el-button
  208. >
  209. <el-button type="primary" @click="registerLocalDevice()">{{
  210. this.title
  211. }}</el-button>
  212. </div>
  213. </el-dialog>
  214. <el-dialog :visible.sync="dialogTable2" @close='closeDialog'>
  215. <template slot="title">
  216. <div
  217. class="titleZise"
  218. style="font-size: 15px; color: #484848; font-weight: 700"
  219. >
  220. {{ this.cameraNo }}
  221. </div>
  222. </template>
  223. <video
  224. class="hlsVideo monitor-height"
  225. ref="hlsVideo"
  226. style="width: 100%"
  227. controls
  228. preload="true"
  229. muted
  230. ></video>
  231. </el-dialog>
  232. <!-- 导出-->
  233. <a href="" download="" id="xz" style="position: absolute;z-index: -1;opacity: 0;"></a>
  234. </div>
  235. </template>
  236. <script>
  237. // 引入导出Excel表格依赖
  238. import FileSaver from "file-saver";
  239. import Hls from "hls.js";
  240. import { getLocalChannel, getDhDeviceListNew,exportDhDeviceListNew } from "@/api/device/camera";
  241. export default {
  242. name: "javascriptthree",
  243. data() {
  244. return {
  245. // 状态数据字典
  246. statusOptions: [
  247. {
  248. dictLabel:"未知",
  249. dictValue:0
  250. },{
  251. dictLabel:"在线",
  252. dictValue:1
  253. },{
  254. dictLabel:"离线",
  255. dictValue:2
  256. }
  257. ],
  258. cameraTypeOptions:[
  259. {
  260. dictLabel:"枪机",
  261. dictValue:1
  262. },{
  263. dictLabel:"球机",
  264. dictValue:2
  265. },{
  266. dictLabel:"半球",
  267. dictValue:3
  268. },{
  269. dictLabel:"证据通道",
  270. dictValue:4
  271. }
  272. ],
  273. listQuery:{
  274. deviceCode:undefined,
  275. deviceName:undefined,
  276. dwtype:undefined,
  277. pageNo:1,
  278. pageSize:15,
  279. sort:undefined,
  280. },
  281. dialogWidth: "60%",
  282. dialogWidth1: "70%",
  283. formLabelWidth: "130px",
  284. //input输入框--设备id
  285. device_id: "",
  286. //input输入框--设备名称
  287. device_name: "",
  288. dialogTable: false,
  289. gridData: [],
  290. gridData1: [],
  291. dialogTable1: false,
  292. cameraNo: "",
  293. dialogTable2: false,
  294. hls: "",
  295. //动态列表信息存储
  296. tableData:[],
  297. cols: [],
  298. //列表总数存储
  299. totalCount: 0,
  300. // //列表起始页
  301. // pageNo: 1,
  302. // //列表每页长度
  303. // pageSize: 15,
  304. //本地注册弹窗
  305. dialogFormVisible: false,
  306. //公共title (本地注册)
  307. title: "",
  308. //from表单提交
  309. from_data: [],
  310. //本地注册列表单条信息存储
  311. row: "",
  312. status2:false,
  313. value: '',
  314. dialogFormVisible3:false,
  315. starTime:undefined,
  316. endTime:undefined,
  317. hrow:undefined,
  318. loading:true,
  319. query:{
  320. id:undefined,
  321. deviceId:undefined,
  322. uuid:undefined,
  323. cameraType:undefined,
  324. name:undefined,
  325. status:undefined,
  326. pageNo:1,
  327. pageSize:15,
  328. unitType:1,
  329. },
  330. dateDataJlStatus:false,//回放记录时间button状态
  331. //表格自适应高度
  332. tableHeight:undefined,
  333. };
  334. },
  335. mounted() {
  336. },
  337. created() {
  338. this.$once("hook:beforeDestroy", () => {
  339. this.destroyHls();
  340. });
  341. this.getData();
  342. },
  343. methods: {
  344. /** 导出按钮操作 */
  345. handleExport() {
  346. let query = {...this.query};
  347. delete query.pageNo
  348. delete query.pageSize
  349. exportDhDeviceListNew(query).then(response =>{
  350. this.exportLoading = false;
  351. document.getElementById("xz").href = 'http://10.21.39.1:8082/archive/' + response.data
  352. document.getElementById("xz").download = response.data
  353. document.getElementById("xz").click()
  354. })
  355. },
  356. /** 重置按钮操作 */
  357. resetQuery() {
  358. this.query = {
  359. id:undefined,
  360. deviceId:undefined,
  361. uuid:undefined,
  362. cameraType:undefined,
  363. name:undefined,
  364. status:undefined,
  365. pageNo:1,
  366. pageSize:15,
  367. unitType:1,
  368. },
  369. this.handleQuery();
  370. },
  371. /** 搜索按钮操作 */
  372. handleQuery() {
  373. this.getData();
  374. },
  375. //同步信息
  376. getDhDeviceListNew(){
  377. getDhDeviceListNew().then((res)=>{
  378. this.$message.success("数据同步请求已发送,请稍后刷新查看")
  379. })
  380. },
  381. //回放时间选项
  382. dateData(val){
  383. this.starTime = new Date(val[0]).getTime()
  384. this.endTime = new Date(val[1]).getTime()
  385. this.dialogFormVisible3 = false
  386. this.playH(this.starTime/1000,this.endTime/1000)
  387. },
  388. //记录回放时间选项
  389. dateDataJl(){
  390. this.dialogFormVisible3 = false
  391. this.playH(this.starTime/1000,this.endTime/1000)
  392. },
  393. //数据初始化
  394. getData(){
  395. let arr = []
  396. getLocalChannel(this.query).then(Response =>{
  397. for(let i = 0; i<Response.data.pageList.length; i++){
  398. arr[i] = {}
  399. arr[i] = Response.data.pageList[i]
  400. }
  401. this.tableData = arr
  402. this.totalCount = Response.data.totalCount
  403. this.loading = false
  404. this.status2 = true
  405. })
  406. },
  407. Select() {
  408. this.Select_DeviceList();
  409. },
  410. Select_DeviceList(data) {
  411. var that = this;
  412. that.cols = [
  413. {
  414. property: "id",
  415. label: "设备id",
  416. width: "",
  417. },
  418. // {
  419. // property:"uuid",
  420. // label:"设备唯一编码",
  421. // width:""
  422. // },
  423. {
  424. property: "name",
  425. label: "设备名称",
  426. width: "",
  427. },
  428. {
  429. property: "deviceIp",
  430. label: "设备IP",
  431. width: "",
  432. },
  433. {
  434. property: "manufacturer",
  435. label: "厂商类型",
  436. width: "",
  437. },
  438. {
  439. property: "unitnum",
  440. label: "单元数目",
  441. width: "",
  442. },
  443. {
  444. property: "devicePort",
  445. label: "设备端口",
  446. width: "",
  447. },
  448. {
  449. property: "registerStatus",
  450. label: "本地注册",
  451. width: "",
  452. },
  453. {
  454. property: "status",
  455. label: "设备状态",
  456. width: "",
  457. },
  458. ];
  459. //获取视频设备列表
  460. api.getLocalDeviceList(data).then((request) => {
  461. that.tableData = [];
  462. that.totalCount = request.totalCount;
  463. for (let i = 0; i < request.pageList.length; i++) {
  464. var pageList = request.pageList[i];
  465. that.tableData.push(pageList);
  466. pageList.manufacturer == 1
  467. ? (pageList.manufacturer = "大华")
  468. : pageList.manufacturer == 2
  469. ? (pageList.manufacturer = "海康")
  470. : (pageList.manufacturer = "未知");
  471. pageList.status == 1
  472. ? (pageList.status = "在线")
  473. : pageList.status == 2
  474. ? (pageList.status = "离线")
  475. : "";
  476. }
  477. });
  478. },
  479. //分页查询
  480. handleCurrentChange(val) {
  481. this.query.pageNo = val;
  482. this.getData();
  483. },
  484. //分页查询
  485. handleSizeChange(val) {
  486. this.query.pageSize = val;
  487. this.getData();
  488. },
  489. handleEdit(index, row) {
  490. var that = this;
  491. that.title = "本地注册";
  492. that.row = row;
  493. that.from_data = [
  494. {
  495. prop: "buildUuid",
  496. label: "建筑名称:",
  497. value: "",
  498. array: [],
  499. bool: true,
  500. },
  501. {
  502. prop: "floorUuid",
  503. label: "楼层名称:",
  504. value: "",
  505. array: [],
  506. bool: false,
  507. },
  508. // { prop: "roomUuid", label: "房间名称:", value: "" ,array: [],bool: false},
  509. {prop: "deviceUuid", label: "楼层ID:", value: "" ,array: [] , bool: false}
  510. ];
  511. api
  512. .queryBuild({
  513. buildAddr: "",
  514. buildName: "",
  515. latitude: "",
  516. longitude: "",
  517. pageNo: "",
  518. pageSize: "",
  519. })
  520. .then((requset) => {
  521. for (let i = 0; i < requset.pageList.length; i++) {
  522. var pageList = requset.pageList[i];
  523. that.from_data[0].array.push({
  524. label: pageList.buildName,
  525. value: pageList.buildUuid,
  526. });
  527. }
  528. });
  529. that.dialogFormVisible = true;
  530. },
  531. select_Value(index) {
  532. var that = this;
  533. if (index == 0) {
  534. that.from_data[1].array = [];
  535. that.from_data[1].value = "";
  536. api
  537. .queryFloor({
  538. floorBuildUuid: that.from_data[index].value,
  539. floorName: "",
  540. pageNo: "",
  541. pageSize: "",
  542. })
  543. .then((requset) => {
  544. var requset = requset.pageList;
  545. if (requset.length > 0) {
  546. that.from_data[1].bool = true;
  547. for (let i = 0; i < requset.length; i++) {
  548. var pageList = requset[i];
  549. that.from_data[1].array.push({
  550. label: pageList.floorName,
  551. value: pageList.floorUuid,
  552. });
  553. }
  554. } else {
  555. that.from_data[1].bool = false;
  556. }
  557. });
  558. api.queryThingsjFloorId().then((requset)=>{
  559. if (requset.data.length > 0) {
  560. that.from_data[2].bool = true;
  561. for (let i = 0; i < requset.data.length; i++) {
  562. var pageList = requset.data[i];
  563. that.from_data[2].array.push({
  564. label: pageList.thingjsFloorId,
  565. value: pageList.thingjsFloorId,
  566. });
  567. }
  568. }else{
  569. that.from_data[2].bool = false;
  570. }
  571. })
  572. }
  573. },
  574. registerLocalDevice() {
  575. var that = this;
  576. var row = that.row;
  577. var from = that.from_data;
  578. api
  579. .registerLocalDevice({
  580. buildUuid: from[0].value,
  581. deviceIp: row.deviceIp,
  582. devicePort: row.devicePort,
  583. floorUuid: from[1].value,
  584. thingjsFloor: from[2].value,
  585. nvrIp: row.nvrIp,
  586. nvrPort: row.nvrPort,
  587. deviceName:row.name,
  588. status: row.registerStatus === "已注册" ? 0 : 1,
  589. })
  590. .then((requset) => {
  591. this.dialogFormVisible = false
  592. this.Select();
  593. });
  594. },
  595. //播放按钮
  596. play(row) {
  597. this.destroyHls()
  598. let url = "http://" + row.nvr_ip + ":" + row.hls_port + "/live/cameraid/" + row.deviceId + "%24" + row.id.split("$")[(row.id.split("$")).length-1] + "/substream/1.m3u8"
  599. this.loadVideoFn(url)
  600. },
  601. //回放url
  602. playH(start,end){
  603. this.destroyHls()
  604. let row = this.hrow
  605. let url = "http://" + row.nvr_ip + ":" + row.hls_port + "/vod/device/cameraid/" + row.deviceId + "%24" + row.id.split("$")[(row.id.split("$")).length-1] + "/substream/1/recordtype/1/totallength/" + Number(end-start) + "/begintime/" + start + "/endtime/" + end + ".m3u8"
  606. this.loadVideoFn(url)
  607. },
  608. destroyHls: function () {
  609. if (this.hls) {
  610. this.$refs.hlsVideo.pause();
  611. this.hls.destroy();
  612. this.hls = null;
  613. }
  614. },
  615. loadVideoFn(url) {
  616. this.dialogTable2 = true
  617. setTimeout(() =>{
  618. if (Hls.isSupported()) {
  619. this.hls = new Hls();
  620. this.hls.loadSource(url);
  621. this.hls.attachMedia(this.$refs.hlsVideo);
  622. this.hls.on(Hls.Events.MANIFEST_PARSED, () => {
  623. console.log("加载成功");
  624. this.$refs.hlsVideo.play();
  625. });
  626. this.hls.on(Hls.Events.ERROR, (event, data) => {
  627. // console.log(event, data);
  628. // 监听出错事件
  629. console.log("加载失败");
  630. });
  631. }
  632. },1000)
  633. },
  634. //设备列表序号
  635. indexMethod(index) {
  636. return index + 1;
  637. },
  638. //回放视频
  639. Hplay(row){
  640. this.dialogFormVisible3 = true
  641. if(this.endTime){
  642. this.dateDataJlStatus = true
  643. }else{
  644. this.dateDataJlStatus = false
  645. }
  646. this.hrow = row
  647. },
  648. //关闭弹框
  649. closeDialog(){
  650. this.destroyHls()
  651. },
  652. },
  653. };
  654. </script>
  655. <style>
  656. .el-dialog__headerbtn{
  657. top:3px;
  658. }
  659. .el-range-editor.el-input__inner{
  660. width:80%;
  661. margin:0 10% !important;
  662. }
  663. .pickerBut{
  664. width:10%;display: inline-block;
  665. margin:20px 45% 0;
  666. }
  667. .el-date-range-picker{
  668. width:520px !important
  669. }
  670. </style>