index.js 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757
  1. /*
  2. * 本文件仅供demo使用
  3. */
  4. let curLang = 'SimpChinese';
  5. //webpack中引用此代码块,格式不要随意改动
  6. //开发模式需要import,打包给3.0的变成了全局变量,不需要
  7. document.querySelector('#device_ipc_tab').addEventListener('click', (event) => {
  8. event.target.style.color = 'blue';
  9. document.querySelector('#device_ipc_content').style.display = '';
  10. ipcFunc();
  11. });
  12. document.querySelector('#onChangeLanguage').addEventListener('change', (event) => {
  13. let val = event.target.value;
  14. curLang = val;
  15. languageTrans();
  16. });
  17. const ipcFunc = () => {
  18. let $stream,
  19. $volume,
  20. $canvas, //canvas播放视频DOM
  21. $video, //video播放视频DOM
  22. $ivsCanvas,
  23. $detectCanvas,
  24. $drawCanvas, //canvas绘图DOM
  25. $video_wrap, //视频外层Wrap
  26. $videoLoading, //“加载中...”提示
  27. WndIndex = 0; //宫格窗口Id
  28. let channel = 0; //当前通道
  29. let curPage = 1; //视频下载列表的当前页
  30. let totalPage = 1; //视频下载列表的总页数
  31. let recordArr = []; //视频文件数组
  32. let canvasInstance = null; //canvas绘图实例
  33. let playerInstance = []; //预览实例数组
  34. let speedX = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1];
  35. let recordInstance = []; //录像下载实例数组
  36. let talkInstance = []; //对讲实例数组
  37. let drawInstance = []; //canvas绘图实例数组
  38. let cutInstance = []; //视频裁剪实例数组
  39. let ivsInstance = []; //智能帧实例数组
  40. let positionInstance = []; //快读定位实例数组
  41. let isCuting = false; //是否正在进行视频裁剪
  42. let downList = []; //勾选的视频下载列表
  43. let downItemIndex = 0; //视频下载索引
  44. let canvasParam = { //canvas绘图默认传参
  45. 'strokeColor': '#FFFF00',
  46. 'title': '',
  47. 'resizeEnable': false,
  48. 'moveEnable': false,
  49. 'closeEnable': true,
  50. 'array': true,
  51. 'showSize': false,
  52. 'selectType': 'inSide',
  53. 'disappear': true,
  54. 'selected': true
  55. }
  56. let curDeviceIndex = 0;
  57. const lINENUMBER = 16; //回放列表每页显示录像条数
  58. let deviceObject = {
  59. loginState: [],
  60. session: []
  61. }
  62. let isStartAll = false;
  63. let curEnlargeWnd = 0;
  64. let _doc = document.getElementById('device_ipc_content');
  65. let playbackOptions = {};
  66. let ChannelPTZCaps = [];
  67. /**
  68. * @description 初始化
  69. */
  70. const init = () => {
  71. let videoStr = '';
  72. for(let i = 0; i < 16; i++) {
  73. videoStr += '<div wnd-index="' + i + '" style="float: left; background-color: #000; position: relative; width: 100%; height: 100%;overflow:hidden;border:1px solid rgb(125,125,125)">' +
  74. '<canvas id="h5_canvas_' + i + '" style="width:100%;height:100%;"></canvas>' +
  75. '<p id="h5_loading_' + i + '" class="video_loading" style="display:none">加载中...</p>' +
  76. '<video id="h5_video_' + i + '" style="display: none;width:100%;height:100%;position:absolute;top:0;left:0"></video>' +
  77. '<canvas id="h5_ivs_' + i + '" style="position: absolute;left: 0;top: 0;width: 100%;height: 100%;" width="500" height="300"></canvas>' + //智能帧的canvas
  78. '<canvas id="h5_detect_' + i + '" style="position: absolute;left: 0;top: 0;width: 100%;height: 100%;" width="500" height="300"></canvas>' + //智能区域的canvas
  79. '<canvas id="h5_draw_' + i + '" style="position: absolute;left: 0;top: 0;width: 100%;height: 100%;" width="500" height="300"></canvas>' + //绘制的canvas
  80. '</div>';
  81. }
  82. _doc.querySelector('.h5-play-wrap').innerHTML = videoStr;
  83. _doc.querySelectorAll('.h5-play-wrap div').forEach((item, index) => {
  84. item.addEventListener('click', function(event) {
  85. let _wndIndex = event.target.parentNode.getAttribute('wnd-index') - 0;
  86. _doc.querySelectorAll('.h5-play-wrap div').forEach(function(item, index) {
  87. if(index === _wndIndex) {
  88. item.style.borderColor = 'rgb(255, 204, 0)';
  89. WndIndex = _wndIndex;
  90. curDeviceIndex = item.getAttribute('deviceindex') - 0;
  91. setVideoDom();
  92. } else {
  93. item.style.borderColor = 'rgb(125, 125, 125)';
  94. }
  95. });
  96. document.getElementById('currentTimes').innerText = speedX[WndIndex] + 'X';
  97. })
  98. });
  99. let deviceDom = _doc.querySelectorAll('.h5-menu-list li');
  100. deviceObject.loginState = new Array(deviceDom.length).fill(false);
  101. deviceObject.session = new Array(deviceDom.length).fill(0);
  102. deviceDom.forEach(function(item, index) {
  103. item.addEventListener('click', async () => {
  104. await onLogout();
  105. curDeviceIndex = index;
  106. onLogin();
  107. });
  108. });
  109. $stream = $('#h5_stream');
  110. $volume = $('#h5_volume');
  111. $video_wrap = _doc.querySelector('.h5-play-wrap');
  112. setVideoDom();
  113. let inputArr = _doc.querySelectorAll('input[btn-for]');
  114. for(let node of inputArr) {
  115. node.addEventListener('click', bindClickEvent);
  116. }
  117. let selArr = _doc.querySelectorAll('select[sel-for]');
  118. for(let node of selArr) {
  119. node.addEventListener('change', bindChangeEvent);
  120. }
  121. $volume.addEventListener('input', function(event) {
  122. let vol = event.target.value - 0;
  123. $('#h5_volume_value').innerText = vol;
  124. });
  125. $volume.addEventListener('change', function(event) {
  126. let vol = event.target.value - 0;
  127. if(playerInstance[WndIndex]) {
  128. playerInstance[WndIndex].setAudioVolume(vol);
  129. }
  130. });
  131. $('#h5_first').addEventListener('click', function() {
  132. if(curPage != 1) {
  133. curPage = 1;
  134. updateTable();
  135. }
  136. });
  137. $('#h5_pre').addEventListener('click', function() {
  138. if(curPage > 1) {
  139. curPage = curPage - 1;
  140. updateTable();
  141. }
  142. });
  143. $('#h5_next').addEventListener('click', function() {
  144. if(curPage < totalPage) {
  145. curPage = curPage + 1;
  146. updateTable();
  147. }
  148. });
  149. $('#h5_last').addEventListener('click', function() {
  150. if(curPage != totalPage) {
  151. curPage = totalPage;
  152. updateTable();
  153. }
  154. });
  155. $('#h5_goPage').addEventListener('click', function() {
  156. let val = $('#h5_goNumber').value - 0;
  157. if(curPage != val) {
  158. curPage = val;
  159. updateTable();
  160. }
  161. });
  162. _doc.querySelectorAll('.testButton').forEach(item => {
  163. item.addEventListener('click', async function(event) {
  164. // 阻止事件冒泡和默认行为
  165. event.stopPropagation();
  166. event.preventDefault();
  167. event.stopImmediatePropagation(); // 阻止同一元素上的其他监听器
  168. // 获取点击的li元素
  169. let liElement = event.target.parentNode;
  170. // 获取所有li元素列表
  171. let deviceDom = _doc.querySelectorAll('.h5-menu-list li');
  172. // 找到当前li在列表中的索引
  173. let deviceIndex = Array.from(deviceDom).indexOf(liElement);
  174. console.log('测试按钮被点击,设备索引:', deviceIndex); // 调试信息
  175. if(deviceIndex !== -1) {
  176. // 先登出当前窗口的设备
  177. await onLogout();
  178. // 设置当前设备索引
  179. curDeviceIndex = deviceIndex;
  180. // 登录并播放该设备
  181. onLogin();
  182. } else {
  183. alert('无法找到设备信息!');
  184. }
  185. return false; // 额外确保阻止默认行为
  186. }, true); // 使用捕获阶段,确保先处理
  187. });
  188. ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'msfullscreenchange'].forEach((item, index) => {
  189. document.addEventListener(item, fullscreenchange, false);
  190. });
  191. onChangeWdnNum();
  192. }
  193. /**
  194. * @description 切换宫格时重新设置当前视频dom
  195. */
  196. const setVideoDom = () => {
  197. $canvas = $('#h5_canvas_' + WndIndex);
  198. $video = $('#h5_video_' + WndIndex);
  199. $drawCanvas = $('#h5_draw_' + WndIndex);
  200. $videoLoading = $('#h5_loading_' + WndIndex);
  201. $ivsCanvas = $('#h5_ivs_' + WndIndex);
  202. $detectCanvas = $('#h5_detect_' + WndIndex);
  203. let _session = deviceObject.session[curDeviceIndex];
  204. let _dom = _doc.querySelector('.h5-menu-list li:nth-child('+(curDeviceIndex+1)+')');
  205. let ip = _dom.getAttribute('data-ip');
  206. let port = _dom.getAttribute('data-port');
  207. setIP(ip + ':' + port);
  208. if(_session !== 0) {
  209. _setSession(_session);
  210. }
  211. }
  212. /**
  213. * @description 登录之后调用,获取设备能力,获取通道、码流
  214. */
  215. const afterLogin = () => {
  216. deviceObject.loginState[curDeviceIndex] = true;
  217. deviceObject.session[curDeviceIndex] = _getSession();
  218. $stream.options.length = 0;
  219. $('#h5_playback_channel').options.length = 0;
  220. $('#h5_channel').options.length = 0;
  221. /**
  222. * RPC.MagicBox.getProductDefinition 获取产品定义
  223. * @param {string} 'MaxExtraStream' 定义名称
  224. * @returns {Promise}
  225. */
  226. RPC.MagicBox.getProductDefinition('MaxExtraStream').then(function(params) {
  227. let maxExtra = params.definition;
  228. let main, extra;
  229. main = new Option(tl('com.MainStream'), 0);
  230. main.setAttribute('t', 'com.MainStream');
  231. $stream.options.add(main);
  232. if (maxExtra > 1) {
  233. for(let i = 1; i <= maxExtra; i++) {
  234. extra = new Option(tl('com.ExtraStream') + i, i);
  235. extra.setAttribute('t', 'com.ExtraStream' + i);
  236. $stream.options.add(extra);
  237. }
  238. } else {
  239. extra = new Option(tl('com.ExtraStream'), 1);
  240. extra.setAttribute('t', 'com.ExtraStream');
  241. $stream.options.add(new Option(tl('com.ExtraStream'), 1));
  242. }
  243. // 默认使用子码流(如果存在),以降低分辨率和内存占用
  244. try {
  245. if ($stream && $stream.options && $stream.options.length > 1) {
  246. // 0 是主码流,从 1 开始为子码流
  247. $stream.value = '1';
  248. } else if ($stream && $stream.options && $stream.options.length > 0) {
  249. $stream.value = '0';
  250. }
  251. } catch (e) {
  252. console.warn('[DAHUA] set default stream failed:', e);
  253. }
  254. });
  255. RPC.DevVideoInput.getCollect().then(function (params) {
  256. let chnls = params.channels;
  257. for(let i = 0; i < chnls;i++) {
  258. $('#h5_playback_channel').options.add(new Option(i+1,i));
  259. $('#h5_channel').options.add(new Option(i+1,i));
  260. }
  261. });
  262. RPC.PTZManager('getCurrentProtocolCaps',channel).then(res => {
  263. ChannelPTZCaps[channel] = res?.caps;
  264. }).catch(err => {console.log(err);});
  265. let curDate = new Date();
  266. let dateString = curDate.toLocaleDateString();
  267. let dateSplit = dateString.split('/');
  268. let month = dateSplit[1] - 0;
  269. if(month < 10) {
  270. dateSplit[1] = '0' + month;
  271. }
  272. let day = dateSplit[2] - 0;
  273. if(day < 10) {
  274. dateSplit[2] = '0' + day;
  275. }
  276. let date = dateSplit.join('-');
  277. $('#h5_startTime').value = date + 'T' + '00:00';
  278. $('#h5_endTime').value = date + 'T' + '23:59:59';
  279. }
  280. const onStartAll = async () => {
  281. await onLogoutAll()
  282. curDeviceIndex = 0;
  283. _doc.querySelector('#h5_draw_' + curDeviceIndex).click();
  284. isStartAll = true;
  285. onLogin();
  286. }
  287. /**
  288. * @description 登录
  289. */
  290. const onLogin = () => {
  291. let _dom = _doc.querySelector('.h5-menu-list li:nth-child('+(curDeviceIndex+1)+')');
  292. let ip = _dom.getAttribute('data-ip');
  293. let port = _dom.getAttribute('data-port');
  294. let name = _dom.getAttribute('data-user');
  295. let pswd = _dom.getAttribute('data-pswd');
  296. let target = ip + ':' + port;
  297. setIP(target);
  298. RPC.login(name, pswd, false).then((res) => {
  299. setCookie('DWebClientSessionID', '', -1);
  300. setCookie('DhWebClientSessionID', '', -1);
  301. /**
  302. * RPC.keepAlive 保活
  303. */
  304. RPC.keepAlive(300, 60000, _getSession(), target, WndIndex);
  305. afterLogin();
  306. onRealPreview(ip,port,name,pswd);//登录后拉流
  307. }).catch((err) => {
  308. console.log(err);
  309. loginError(err);
  310. $videoLoading.style.display = '';
  311. $videoLoading.innerText = tl('com.OpenFailed'); //打开失败!
  312. let curWndType = _doc.querySelector('[sel-for=onChangeWdnNum]').value - 0;
  313. let _newDom = _doc.querySelector('.h5-menu-list li:nth-child(' + (curDeviceIndex + 2) + ')');
  314. if(curWndType !== 1 && _newDom != null && isStartAll) {
  315. clickNextWnd();
  316. _newDom.click();
  317. };
  318. });
  319. }
  320. const onRealPreview = (ip,port,name,pswd) => {
  321. if(playerInstance[WndIndex]) {
  322. playerInstance[WndIndex].stop();
  323. playerInstance[WndIndex].close();
  324. playerInstance[WndIndex] = null;
  325. let dom = $canvas;
  326. if (dom.style.display === 'none') {
  327. dom = $video;
  328. }
  329. dom.style.display = 'none';
  330. }
  331. let player = null;
  332. let curChannel = channel + 1; //无插件通道号从1开始
  333. let stream = $stream.value - 0;
  334. let options = {
  335. wsURL: 'ws://'+ ip +':' + port + '/rtspoverwebsocket',
  336. rtspURL: 'rtsp://'+ ip +':' + port + '/cam/realmonitor?channel=' + curChannel + '&subtype='+ stream +'&proto=Private3',
  337. username: name,
  338. password: pswd,
  339. lessRateCanvas:true,
  340. wndIndex: WndIndex,
  341. h265AccelerationEnabled: true
  342. };
  343. player = new PlayerControl(options);
  344. player.on('MSEResolutionChanged', function (e) {
  345. console.log(e)
  346. });
  347. player.on('PlayStart', function (e) {
  348. console.log(e);
  349. $canvas.parentNode.setAttribute('deviceindex', curDeviceIndex);
  350. $videoLoading.style.display = 'none';
  351. $ivsCanvas.style.display = '';
  352. let curWndType = _doc.querySelector('[sel-for=onChangeWdnNum]').value - 0;
  353. let _newDom = _doc.querySelector('.h5-menu-list li:nth-child(' + (curDeviceIndex + 2) + ')');
  354. let hasLoginNum = getLoginState();
  355. if(curWndType !== 1 && _newDom != null && isStartAll && hasLoginNum < curWndType * curWndType) {
  356. clickNextWnd();
  357. _newDom.click();
  358. } else {
  359. isStartAll = false;
  360. }
  361. });
  362. player.on('DecodeStart', function (e) {
  363. console.log(e)
  364. if(e.decodeMode === 'video'){
  365. $canvas.style.display = 'none';
  366. $video.style.display = '';
  367. }else{
  368. $video.style.display = 'none';
  369. $canvas.style.display = '';
  370. }
  371. canvasInstance = new PluginCanvasES6();
  372. let instance = new H5Canvas($ivsCanvas, $drawCanvas, $detectCanvas, WndIndex);
  373. canvasInstance.init($drawCanvas, function (data) {
  374. rebackActivateLocalEnlarging(data);
  375. });
  376. canvasInstance.addChangeShapeEvent();
  377. playerInstance[WndIndex] = player;
  378. drawInstance[WndIndex] = canvasInstance;
  379. ivsInstance[WndIndex] = instance;
  380. });
  381. player.on('GetFrameRate', function (e) {
  382. console.log('GetFrameRate: ' + e)
  383. });
  384. player.on('FrameTypeChange', function (e) {
  385. console.log('FrameTypeChange: ' + e)
  386. });
  387. player.on('Error', function (e) {
  388. //console.log('Error: ' + JSON.stringify(e))
  389. });
  390. player.on('WorkerReady',function(){
  391. player.connect();
  392. });
  393. player.on('IvsDraw', function(data, index) {
  394. let ivsShow = $('#h5_ivs').value;
  395. let winID = index;
  396. if(ivsShow === '1') {
  397. ivsInstance[winID] && ivsInstance[winID].receiveDataFromStream(data, 0);
  398. } else {
  399. ivsInstance[winID] && ivsInstance[winID].close();
  400. }
  401. });
  402. player.init($canvas, $video);
  403. $videoLoading.style.display = '';
  404. $videoLoading.innerText = tl('com.Loading');
  405. }
  406. const onPlayBack = (url, index) => {
  407. if(playerInstance[WndIndex]) {
  408. playerInstance[WndIndex].stop();
  409. playerInstance[WndIndex].close();
  410. playerInstance[WndIndex] = null;
  411. let dom = $canvas;
  412. if (dom.style.display === 'none') {
  413. dom = $video;
  414. }
  415. dom.style.display = 'none';
  416. }
  417. let ip = playbackOptions.ip;
  418. let port = playbackOptions.port;
  419. let name = playbackOptions.name;
  420. let pswd = playbackOptions.pswd;
  421. let player = null;
  422. let firstTime = 0;
  423. let options = {
  424. wsURL: 'ws://'+ ip +':' + port + '/rtspoverwebsocket',
  425. rtspURL: 'rtsp://'+ ip +':' + port + '/' + url,
  426. username: name,
  427. password: pswd,
  428. lessRateCanvas:true,
  429. playbackIndex: index,
  430. wndIndex: WndIndex
  431. };
  432. player = new PlayerControl(options);
  433. player.on('UpdateCanvas', function (e) {
  434. let playbackIndex = player.playbackIndex;
  435. let _index = playbackIndex%16;
  436. if(firstTime === 0){
  437. firstTime = e.timestamp;//获取录像文件的第一帧的时间戳
  438. }
  439. $('#h5_curTime_'+ _index).innerText = e.timestamp - firstTime;
  440. });
  441. player.on('GetTotalTime', function (e) {
  442. let playbackIndex = player.playbackIndex;
  443. let _index = playbackIndex%16;
  444. $('#h5_totalTime_'+ _index).innerText = e;
  445. });
  446. player.on('MSEResolutionChanged', function (e) {
  447. console.log(e)
  448. });
  449. player.on('PlayStart', function (e) {
  450. console.log(e);
  451. $canvas.parentNode.setAttribute('deviceindex', curDeviceIndex);
  452. $videoLoading.style.display = 'none';
  453. $ivsCanvas.style.display = '';
  454. });
  455. player.on('DecodeStart', function (e) {
  456. console.log(e)
  457. if(e.decodeMode === 'video'){
  458. $video.style.display = '';
  459. $canvas.style.display = 'none';
  460. }else{
  461. $video.style.display = 'none';
  462. $canvas.style.display = '';
  463. }
  464. canvasInstance = new PluginCanvasES6();
  465. let instance = new H5Canvas($ivsCanvas, $drawCanvas, $detectCanvas, WndIndex);
  466. canvasInstance.init($drawCanvas, function (data) {
  467. rebackActivateLocalEnlarging(data);
  468. });
  469. canvasInstance.addChangeShapeEvent();
  470. playerInstance[WndIndex] = player;
  471. drawInstance[WndIndex] = canvasInstance;
  472. ivsInstance[WndIndex] = instance;
  473. });
  474. player.on('GetFrameRate', function (e) {
  475. console.log('GetFrameRate: ' + e)
  476. });
  477. player.on('FrameTypeChange', function (e) {
  478. console.log('FrameTypeChange: ' + e)
  479. });
  480. player.on('FileOver', function (e) {
  481. player.close();
  482. });
  483. player.on('IvsDraw', function(data, index) {
  484. let ivsShow = $('#h5_ivs').value;
  485. let winID = index;
  486. if(ivsShow === '1') {
  487. ivsInstance[winID] && ivsInstance[winID].receiveDataFromStream(data, 0);
  488. } else {
  489. ivsInstance[winID] && ivsInstance[winID].close();
  490. }
  491. });
  492. player.on('Error', function (e) {
  493. //console.log('Error: ' + JSON.stringify(e))
  494. });
  495. player.on('WorkerReady',function() {
  496. player.connect();
  497. });
  498. player.init($canvas, $video);
  499. $videoLoading.style.display = '';
  500. $videoLoading.innerText = tl('com.Loading');
  501. }
  502. const getLoginState = () => {
  503. let num = 0;
  504. deviceObject.loginState.map(item => {
  505. if(item === true) {
  506. num++;
  507. }
  508. });
  509. return num;
  510. }
  511. const clickNextWnd = () => {
  512. let curWndType = _doc.querySelector('[sel-for=onChangeWdnNum]').value - 0;
  513. if(curWndType === 2 && WndIndex === 3 || curWndType === 3 && WndIndex === 8 || curWndType === 4 && WndIndex === 15) {
  514. // _doc.querySelector('#h5_draw_0').click();
  515. } else {
  516. _doc.querySelector('#h5_draw_' + (WndIndex + 1)).click();
  517. }
  518. }
  519. /**
  520. * @description 关闭拉流
  521. */
  522. const onStopPreview = () => {
  523. if(playerInstance[WndIndex]) {
  524. playerInstance[WndIndex].stop();
  525. playerInstance[WndIndex].close();
  526. playerInstance[WndIndex] = null;
  527. let dom = $canvas;
  528. if (dom.style.display === 'none') {
  529. dom = $video;
  530. }
  531. dom.style.display = 'none';
  532. }
  533. if(talkInstance[WndIndex]) {
  534. talkInstance[WndIndex].talk('off');
  535. talkInstance[WndIndex] = null;
  536. }
  537. if(recordInstance[WndIndex]) {
  538. recordInstance[WndIndex].startRecord(false);
  539. recordInstance[WndIndex] = null;
  540. }
  541. $videoLoading.style.display = 'none';
  542. $ivsCanvas.style.display = 'none';
  543. }
  544. const onStopAllPreview = () => {
  545. for(let i = 0; i < playerInstance.length; i++) {
  546. if(playerInstance[i]) {
  547. playerInstance[i].stop();
  548. playerInstance[i].close();
  549. playerInstance[i] = null;
  550. let canvasDom = $('#h5_canvas_' + i);
  551. let videoDom = $('#h5_video_' + i);
  552. let ivsCanvas = $('#h5_ivs_' + i);
  553. let dom = canvasDom;
  554. if (dom.style.display === 'none') {
  555. dom = videoDom;
  556. }
  557. dom.style.display = 'none';
  558. ivsCanvas.style.display = 'none';
  559. }
  560. }
  561. talkInstance.forEach(item => {
  562. if(item) {
  563. item.talk('off');
  564. item = null;
  565. }
  566. });
  567. recordInstance.forEach(item => {
  568. if(item) {
  569. item.startRecord(false);
  570. item = null;
  571. }
  572. });
  573. _doc.querySelectorAll('[id^=h5_loading_]').forEach(item => {
  574. item.style.display = 'none';
  575. });
  576. }
  577. const startFastPostion = () => {
  578. onStopEnlarge();
  579. if(!positionInstance[WndIndex]) {
  580. positionInstance[WndIndex] = new PluginCanvasES6();
  581. positionInstance[WndIndex].init($drawCanvas, function (data) {
  582. fastPostionEvent(data);
  583. });
  584. positionInstance[WndIndex].addChangeShapeEvent();
  585. }
  586. positionInstance[WndIndex].setRegionNum('rect', 1);
  587. positionInstance[WndIndex].drawStart('rect', {...canvasParam});
  588. const fastPostionEvent = (data) => {
  589. let pos = data.data;
  590. let left = pos[0][0];
  591. let top = pos[0][1];
  592. let right = pos[1][0];
  593. let bottom = pos[1][1];
  594. let x = (right + left) / (2 * 8192),
  595. y = (bottom + top) / (2 * 8192);
  596. let maxlength = Math.abs(bottom - top) > Math.abs(right - left) ? (bottom - top) : (right - left);
  597. let zoomtemp = (maxlength / 8192);
  598. let zoom = (right - left) > 0 ? zoomtemp * zoomtemp : (-1) * zoomtemp * zoomtemp;
  599. let request = Promise.resolve();
  600. let useNewApi = ChannelPTZCaps?.[channel]?.MoveDirectly?.Type?.includes('Real');
  601. if(useNewApi) {
  602. request = RPC.PTZBase.moveDirectly({
  603. channel : channel,
  604. startPoint : [left,top],
  605. endPoint : [right, bottom]
  606. });
  607. }else{
  608. request = RPC.PTZManager('moveDirectly',channel,{screen:[x, y, zoom]});
  609. }
  610. request.then(() => {
  611. console.log('快读定位成功!')
  612. });
  613. }
  614. }
  615. const stopFastPostion = () => {
  616. if(positionInstance[WndIndex]) {
  617. positionInstance[WndIndex].removeShapeDrawEvent();
  618. positionInstance[WndIndex] = null;
  619. }
  620. }
  621. /**
  622. * @description 登出当前设备
  623. */
  624. const onLogout = async () => {
  625. let _realDevice = _doc.querySelector('div[wnd-index="'+WndIndex+'"]').getAttribute('deviceindex');
  626. if(_realDevice === null) {
  627. return;
  628. }
  629. let _session = deviceObject.session[curDeviceIndex];
  630. if(_session === 0) {
  631. return;
  632. }
  633. _setSession(_session);
  634. await RPC.Global.logout().then(function() {
  635. if(playerInstance[WndIndex]) {
  636. playerInstance[WndIndex].stop();
  637. playerInstance[WndIndex].close();
  638. playerInstance[WndIndex] = null;
  639. let dom = $canvas;
  640. if (dom.style.display === 'none') {
  641. dom = $video;
  642. }
  643. dom.style.display = 'none';
  644. }
  645. if(talkInstance[WndIndex]) {
  646. talkInstance[WndIndex].talk('off');
  647. talkInstance[WndIndex] = null;
  648. }
  649. if(cutInstance[WndIndex]) {
  650. cutInstance[WndIndex].stop();
  651. cutInstance[WndIndex].close();
  652. cutInstance[WndIndex] = null;
  653. }
  654. if(recordInstance[WndIndex]) {
  655. recordInstance[WndIndex].startRecord(false);
  656. recordInstance[WndIndex] = null;
  657. }
  658. $videoLoading.style.display = 'none';
  659. $ivsCanvas.style.display = 'none';
  660. deviceObject.session[curDeviceIndex] = 0;
  661. deviceObject.loginState[curDeviceIndex] = false;
  662. pubsub.publish('_clearTime_', WndIndex);
  663. curPage = 1;
  664. totalPage = 1;
  665. });
  666. }
  667. /**
  668. * @description 登出全部设备
  669. */
  670. const onLogoutAll = async () => {
  671. for(let i = 0; i < playerInstance.length; i++) {
  672. if(playerInstance[i]) {
  673. playerInstance[i].stop();
  674. playerInstance[i].close();
  675. playerInstance[i] = null;
  676. let canvasDom = $('#h5_canvas_' + i);
  677. let videoDom = $('#h5_video_' + i);
  678. let ivsCanvas = $('#h5_ivs_' + i);
  679. let dom = canvasDom;
  680. if (dom.style.display === 'none') {
  681. dom = videoDom;
  682. }
  683. dom.style.display = 'none';
  684. ivsCanvas.style.display = 'none';
  685. }
  686. }
  687. talkInstance.forEach(item => {
  688. if(item) {
  689. item.talk('off');
  690. item = null;
  691. }
  692. });
  693. recordInstance.forEach(item => {
  694. if(item) {
  695. item.startRecord(false);
  696. item = null;
  697. }
  698. });
  699. _doc.querySelectorAll('[id^=h5_loading_]').forEach(item => {
  700. item.style.display = 'none';
  701. });
  702. let len = deviceObject.session.length; //登出已经登录的全部设备
  703. for (let i = 0; i < len; i++) {
  704. if(deviceObject.session[i] != 0) {
  705. let _dom = _doc.querySelector('.h5-menu-list li:nth-child('+(i+1)+')');
  706. let ip = _dom.getAttribute('data-ip');
  707. let port = _dom.getAttribute('data-port');
  708. setIP(ip + ':' + port);
  709. _setSession(deviceObject.session[i]);
  710. await RPC.Global.logout().then(() => {
  711. deviceObject.session[i] = 0;
  712. deviceObject.loginState[i] = false;
  713. _doc.querySelector('div[wnd-index="'+WndIndex+'"]').removeAttribute('deviceindex');
  714. });
  715. }
  716. }
  717. curPage = 1;
  718. totalPage = 1;
  719. }
  720. /**
  721. * @description 切换码流
  722. */
  723. const onChangeStream = () => {
  724. let _dom = _doc.querySelector('.h5-menu-list li:nth-child('+(curDeviceIndex+1)+')');
  725. let ip = _dom.getAttribute('data-ip');
  726. let port = _dom.getAttribute('data-port');
  727. let name = _dom.getAttribute('data-user');
  728. let pswd = _dom.getAttribute('data-pswd');
  729. onRealPreview(ip, port, name, pswd);
  730. }
  731. /**
  732. * @description 切换通道
  733. */
  734. const onChangeChannel = () => {
  735. channel = $('#h5_channel').value - 0;
  736. let _dom = _doc.querySelector('.h5-menu-list li:nth-child('+(curDeviceIndex+1)+')');
  737. let ip = _dom.getAttribute('data-ip');
  738. let port = _dom.getAttribute('data-port');
  739. let name = _dom.getAttribute('data-user');
  740. let pswd = _dom.getAttribute('data-pswd');
  741. onRealPreview(ip, port, name, pswd);
  742. }
  743. /**
  744. * @description 开启音频
  745. */
  746. const onTurnOnSound = () => {
  747. let vol = $volume.value - 0;
  748. if(playerInstance[WndIndex]) {
  749. playerInstance[WndIndex].setAudioVolume(vol);
  750. }
  751. }
  752. /**
  753. * @description 关闭音频
  754. */
  755. const onTurnSoundOff = () => {
  756. if(playerInstance[WndIndex]) {
  757. playerInstance[WndIndex].setAudioVolume(0);
  758. }
  759. }
  760. /**
  761. * @description 开启对讲
  762. */
  763. const onStartTalk = () => {
  764. let _realDevice = _doc.querySelector('div[wnd-index="'+WndIndex+'"]').getAttribute('deviceindex');
  765. if(_realDevice === null) {
  766. return;
  767. }
  768. let talkPlayer = null;
  769. let _dom = _doc.querySelector('.h5-menu-list li:nth-child(' + (curDeviceIndex + 1) + ')');
  770. let curChannel = channel + 1; //无插件通道号从1开始
  771. let ip = _dom.getAttribute('data-ip');
  772. let port = Number(_dom.getAttribute('data-port'));
  773. let username = _dom.getAttribute('data-user');
  774. let password = _dom.getAttribute('data-pswd');
  775. let rtspURL = 'rtsp://'+ ip +':' + port + '/cam/realmonitor?channel=' + curChannel + '&subtype=5&proto=Private3';
  776. let optionsAudio = {
  777. wsURL: 'ws://'+ ip +':' + port + '/rtspoverwebsocket',
  778. rtspURL: rtspURL,
  779. username: username,
  780. password: password,
  781. isTalkService: true
  782. }
  783. talkPlayer = new PlayerControl(optionsAudio);
  784. talkPlayer.talk('on');
  785. talkInstance[WndIndex] = talkPlayer;
  786. }
  787. /**
  788. * @description 关闭对讲
  789. */
  790. const onStopTalk = () => {
  791. if(talkInstance[WndIndex]) {
  792. talkInstance[WndIndex].talk('off');
  793. talkInstance[WndIndex] = null;
  794. }
  795. }
  796. /**
  797. * @description slow
  798. */
  799. const onSlow = () => {
  800. if(speedX[WndIndex] == null){
  801. speedX[WndIndex] = 1;
  802. }
  803. if(speedX[WndIndex] < 0.125){
  804. return;
  805. }
  806. speedX[WndIndex] = speedX[WndIndex] / 2;
  807. document.getElementById('currentTimes').innerText = speedX[WndIndex] + 'X';
  808. playerInstance[WndIndex].playFF(speedX[WndIndex]);
  809. }
  810. /**
  811. * @description fast
  812. */
  813. const onFast = () => {
  814. if(speedX[WndIndex] == null){
  815. speedX[WndIndex] = 1;
  816. }
  817. if(speedX[WndIndex] > 8){
  818. return;
  819. }
  820. speedX[WndIndex] = speedX[WndIndex] * 2;
  821. document.getElementById('currentTimes').innerText = speedX[WndIndex] + 'X';
  822. playerInstance[WndIndex].playFF(speedX[WndIndex]);
  823. }
  824. /**
  825. * @description 抓图
  826. */
  827. const onSnap = () => {
  828. if(playerInstance[WndIndex]) {
  829. playerInstance[WndIndex].capture('test');
  830. }
  831. }
  832. /**
  833. * @description 获取抓图数据
  834. */
  835. const onGetCapture = () => {
  836. if(playerInstance[WndIndex]) {
  837. let picData = playerInstance[WndIndex].getCapture('jpg', 1.0); //参数释义:type(jpg/jpeg/png),quality(0-1.0)
  838. console.log(picData);
  839. }
  840. }
  841. /**
  842. * @description 针对直播的,开始本地下载
  843. */
  844. const onStartRecord = () => {
  845. let _realDevice = _doc.querySelector('div[wnd-index="'+WndIndex+'"]').getAttribute('deviceindex');
  846. if(_realDevice === null) {
  847. return;
  848. }
  849. let recordPlayer = null;
  850. let _dom = _doc.querySelector('.h5-menu-list li:nth-child(' + (curDeviceIndex + 1) + ')');
  851. let curChannel = channel + 1; //无插件通道号从1开始
  852. let ip = _dom.getAttribute('data-ip');
  853. let port = Number(_dom.getAttribute('data-port'));
  854. let username = _dom.getAttribute('data-user');
  855. let password = _dom.getAttribute('data-pswd');
  856. let stream = $stream.value - 0;
  857. let rtspURL = 'rtsp://'+ ip +':' + port + '/cam/realmonitor?channel=' + curChannel + '&subtype='+ stream +'&proto=Private3';
  858. let optionsRecord = {
  859. wsURL: 'ws://'+ ip +':' + port + '/rtspoverwebsocket',
  860. rtspURL: rtspURL,
  861. username: username,
  862. password: password
  863. }
  864. recordPlayer = new PlayerControl(optionsRecord);
  865. recordPlayer.startRecord(true, {
  866. nameOptions: {
  867. nameFormat: ['{fileName}_ymd_his', {
  868. fileName: 'testFileName'
  869. }]
  870. }
  871. });
  872. recordInstance[WndIndex] = recordPlayer;
  873. $videoLoading.style.display = '';
  874. $videoLoading.innerText = tl('com.Recording'); //录像中!
  875. }
  876. /**
  877. * @description 针对直播的,停止本地下载
  878. */
  879. const onStopRecord = () => {
  880. if(recordInstance[WndIndex]) {
  881. recordInstance[WndIndex].startRecord(false);
  882. recordInstance[WndIndex] = null;
  883. $videoLoading.style.display = 'none';
  884. }
  885. }
  886. /**
  887. * @description 针对回放视频的,视频裁剪
  888. */
  889. const onStartCut = () => {
  890. let _cutIndex = _doc.querySelector('[btn-for=onStartCut]').getAttribute('cutIndex') - 0;
  891. let cutPlayer = null;
  892. let ip = playbackOptions.ip;
  893. let port = playbackOptions.port;
  894. let username = playbackOptions.name;
  895. let password = playbackOptions.pswd;
  896. let url = recordArr[_cutIndex].FilePath;
  897. let _rtspURL = 'rtsp://'+ ip +':' + port + '/' + url;
  898. let cutStartTime = $('#h5_cutStartTime').value;
  899. let s = new Date(cutStartTime.replace('T', ' ')).getTime();
  900. let startTime = new Date(recordArr[_cutIndex].StartTime).getTime();
  901. let range1 = (s - startTime)/1000;
  902. let optionsRecord = {
  903. wsURL: 'ws://'+ ip +':' + port + '/rtspoverwebsocket',
  904. rtspURL: _rtspURL,
  905. username: username,
  906. password: password,
  907. isPrivateProtocol: false, //是否私有协议,默认false
  908. realm: RPC.realm, //登录返回的设备Realm值
  909. speed: 16, //倍速拉流,16倍速
  910. playback: true, //是否是回放
  911. range: range1, //视频裁剪时间与视频的StartTime时间差值
  912. isDownLoad:true
  913. }
  914. cutPlayer = new PlayerControl(optionsRecord);
  915. cutPlayer.on('WorkerReady',function(){
  916. cutPlayer.connect();
  917. });
  918. cutPlayer.on('FileOver',function(){
  919. console.log('File Over');
  920. cutPlayer.startCut(false);
  921. isCuting = false;
  922. $('#h5_cut_process').innerText = '100%';
  923. });
  924. cutPlayer.on('UpdateTimeStamp', function (e) {
  925. let cutStartTime1 = $('#h5_cutStartTime').value;
  926. let cutEndTime1 = $('#h5_cutEndTime').value;
  927. let s1 = new Date(cutStartTime1.replace('T', ' ')).getTime() / 1000;
  928. let e1 = new Date(cutEndTime1.replace('T', ' ')).getTime() / 1000;
  929. let process = parseInt((1 - (e1 - e.timestamp) / (e1 - s1)) * 100);
  930. // console.log(new Date(e.timestamp * 1000));
  931. $('#h5_cut_process').innerText = (process > 100 ? 100 : process) + '%';
  932. if((e.timestamp >= s1) && !isCuting) {
  933. cutPlayer.startCut(true);
  934. isCuting = true;
  935. }
  936. if((e.timestamp >= e1 ) && isCuting) {
  937. cutPlayer.startCut(false);
  938. isCuting = false;
  939. $('#h5_cut_process').innerText = '100%';
  940. }
  941. });
  942. cutPlayer.init($canvas, $video);
  943. cutInstance[WndIndex] = cutPlayer;
  944. }
  945. /**
  946. * @description 开启电子放大
  947. */
  948. const onStartEnlarge = () => {
  949. stopFastPostion();
  950. if (drawInstance[WndIndex]) {
  951. $ivsCanvas.style.display = 'none';
  952. drawInstance[WndIndex].setRegionNum('rect', 1);
  953. let param = {...canvasParam};
  954. drawInstance[WndIndex].drawStart('rect', param);
  955. curEnlargeWnd = WndIndex;
  956. }
  957. }
  958. /**
  959. * @description 开启区域放大
  960. */
  961. const onStartGridEnlarge = () => {
  962. _doc.querySelectorAll('[wnd-index]').forEach((item, index) => {
  963. if(index === WndIndex) {
  964. _doc.querySelector('[wnd-index="' + WndIndex +'"]').style.width = '100%';
  965. _doc.querySelector('[wnd-index="' + WndIndex +'"]').style.height = '100%';
  966. _doc.querySelector('#h5_draw_' + WndIndex).setAttribute('height', 300);
  967. _doc.querySelector('#h5_draw_' + WndIndex).setAttribute('width', 500);
  968. drawInstance[WndIndex] && drawInstance[WndIndex].resize();
  969. } else {
  970. item.style.display = 'none';
  971. }
  972. });
  973. }
  974. /**
  975. * @description 关闭区域放大
  976. */
  977. const onCloseGridEnlarge = () => {
  978. _doc.querySelectorAll('[wnd-index]').forEach((item, index) => {
  979. item.style.display = '';
  980. });
  981. onChangeWdnNum();
  982. }
  983. /**
  984. * @description 关闭电子放大
  985. */
  986. const onStopEnlarge = () => {
  987. let dom = $canvas;
  988. if (dom.style.display === 'none') {
  989. dom = $video;
  990. }
  991. dom.style.width = '100%';
  992. dom.style.height = '100%';
  993. dom.style.left = 0;
  994. dom.style.top = 0;
  995. dom.style.position = 'static';
  996. $ivsCanvas.style.display = '';
  997. }
  998. /**
  999. * @description 绘制电子放大后的回调函数
  1000. * @param {object} data 矩形框的坐标信息
  1001. */
  1002. const rebackActivateLocalEnlarging = data => {
  1003. if(curEnlargeWnd != WndIndex) return;
  1004. let pos = data.data;
  1005. let newData;
  1006. if (pos[0][0] === pos[1][0]) {
  1007. // return false;
  1008. } else {
  1009. newData = {
  1010. left: pos[0][0],
  1011. top: pos[0][1],
  1012. right: pos[1][0],
  1013. bottom: pos[1][1]
  1014. }
  1015. }
  1016. let dom = $canvas;
  1017. if (dom.style.display === 'none') {
  1018. dom = $video;
  1019. }
  1020. // 倒着画
  1021. if (newData.right < newData.left) {
  1022. let tmp = newData.left;
  1023. newData.left = newData.right;
  1024. newData.right = tmp;
  1025. }
  1026. if (newData.bottom < newData.top) {
  1027. let tmp = newData.top;
  1028. newData.top = newData.bottom;
  1029. newData.bottom = tmp;
  1030. }
  1031. let scaleW = $video_wrap.childNodes[WndIndex].clientWidth / 8191;
  1032. let scaleH = $video_wrap.childNodes[WndIndex].clientHeight / 8191;
  1033. let result = zoomArea(newData.left * scaleW, newData.top * scaleH, newData.right * scaleW, newData.bottom * scaleH, $video_wrap.childNodes[WndIndex].clientWidth, $video_wrap.childNodes[WndIndex].clientHeight);
  1034. dom.style.width = result.width + 'px';
  1035. dom.style.height = result.height + 'px';
  1036. dom.style.left = result.left + 'px';
  1037. dom.style.top = result.top + 'px';
  1038. dom.style.position = 'absolute';
  1039. drawInstance[WndIndex].removeShapeDrawEvent();
  1040. }
  1041. /**
  1042. * @description 设置全屏
  1043. */
  1044. const onSetFull = () => {
  1045. if (getFull()) {
  1046. exitfullScreen();
  1047. } else {
  1048. setfullScreen();
  1049. }
  1050. }
  1051. /**
  1052. * @description 切换窗口分割
  1053. */
  1054. const onChangeWdnNum = () => {
  1055. let val = _doc.querySelector('[sel-for=onChangeWdnNum]').value;
  1056. let ivsDom = _doc.querySelectorAll('[id^=h5_draw_]');
  1057. let divDom = _doc.querySelectorAll('.h5-play-wrap div');
  1058. // 限制最大分屏为 2x2,避免开启过多解码实例导致内存溢出
  1059. let rawGrid = parseInt(val, 10) || 1;
  1060. let grid = Math.min(rawGrid, 2);
  1061. if (rawGrid !== grid) {
  1062. // 同步下拉框显示
  1063. let sel = _doc.querySelector('[sel-for=onChangeWdnNum]');
  1064. if (sel) {
  1065. sel.value = String(grid);
  1066. }
  1067. }
  1068. let total = grid * grid;
  1069. // 控制显示数量
  1070. divDom.forEach((item, index) => {
  1071. if (index < total) {
  1072. item.style.display = 'block';
  1073. } else {
  1074. item.style.display = 'none';
  1075. }
  1076. });
  1077. // 设置尺寸
  1078. if(grid === 1) {
  1079. divDom.forEach((item, index) => {
  1080. if(index < total) {
  1081. item.style.width = '100%';
  1082. item.style.height = '100%';
  1083. item.style.borderColor = '#000';
  1084. }
  1085. });
  1086. } else if(grid === 2) {
  1087. divDom.forEach((item, index) => {
  1088. if(index < total) {
  1089. item.style.width = 'calc(50% - 2px)';
  1090. item.style.height = 'calc(50% - 2px)';
  1091. }
  1092. });
  1093. } else if(grid === 3) {
  1094. divDom.forEach((item,index) => {
  1095. if(index < total) {
  1096. item.style.height = 'calc(33.333% - 2px)';
  1097. item.style.width = 'calc(33.333% - 2px)';
  1098. }
  1099. });
  1100. } else if(grid === 4) {
  1101. divDom.forEach((item, index) => {
  1102. if(index < total) {
  1103. item.style.width = 'calc(25% - 2px)';
  1104. item.style.height = 'calc(25% - 2px)';
  1105. }
  1106. });
  1107. }
  1108. // 调整canvas大小,仅对可见窗口
  1109. ivsDom.forEach(item => {
  1110. if (item.parentNode && item.parentNode.style.display !== 'none') {
  1111. item.setAttribute('width', `${item.parentNode.clientWidth}`);
  1112. item.setAttribute('height', `${item.parentNode.clientHeight}`);
  1113. }
  1114. });
  1115. drawInstance.forEach((item, index) => {
  1116. if (divDom[index] && divDom[index].style.display !== 'none') {
  1117. item && item.resize();
  1118. }
  1119. });
  1120. // 默认选中第一个窗口
  1121. let first = _doc.querySelector('#h5_draw_0');
  1122. first && first.click();
  1123. }
  1124. /**
  1125. * @description 自定义选择器
  1126. * @param {string} str dom元素
  1127. */
  1128. function $(str) {
  1129. if(str.charAt(0) == '#') {
  1130. return document.getElementById(str.substring(1));
  1131. } else if(str.charAt(0) == '.') {
  1132. return _doc.getElementsByClassName(str.substring(1));
  1133. } else {
  1134. return _doc.getElementsByTagName(str);
  1135. }
  1136. }
  1137. /**
  1138. * @description 设置样式
  1139. * @param {object} obj dom元素
  1140. * @param {*} json css样式
  1141. */
  1142. function setStyle (obj, json){
  1143. for(let i in json) {
  1144. obj.style[i] = json[i];
  1145. }
  1146. }
  1147. /**
  1148. * @description 绑定click事件
  1149. * @param {object} event event对象
  1150. */
  1151. function bindClickEvent(event) {
  1152. let $el = event.target,
  1153. method = $el.getAttribute('btn-for'),
  1154. disabled = $el.getAttribute('disabled');
  1155. if(!disabled) {
  1156. eval(method + "()");
  1157. }
  1158. }
  1159. /**
  1160. * @description 绑定change事件
  1161. * @param {object} event event对象
  1162. */
  1163. function bindChangeEvent(event) {
  1164. let $el = event.target,
  1165. method = $el.getAttribute('sel-for'),
  1166. disabled = $el.getAttribute('disabled');
  1167. if(!disabled) {
  1168. eval(method + "()");
  1169. }
  1170. }
  1171. /**
  1172. * @description 转换数据坐标
  1173. * @param {*} x1 左上角x坐标
  1174. * @param {*} y1 左上角y坐标
  1175. * @param {*} x2 右下角x坐标
  1176. * @param {*} y2 右下角y坐标
  1177. * @param {*} width 宫格宽
  1178. * @param {*} height 宫格高
  1179. */
  1180. function zoomArea (x1, y1, x2, y2, width, height) {
  1181. // 小框区域的数据
  1182. let rectArea = {
  1183. width: x2 - x1,
  1184. height: y2 - y1,
  1185. centerX: (x1 + x2) / 2, // 圆心坐标
  1186. centerY: (y1 + y2) / 2
  1187. };
  1188. // 放大比例,控件放大倍数上限是20
  1189. let scale = Math.min(width / rectArea.width, height / rectArea.height, 20);
  1190. // 原始窗口信息
  1191. let sourceWin = {
  1192. width: width,
  1193. height: height,
  1194. centerX: width / 2,
  1195. centerY: height / 2
  1196. };
  1197. // 放大后的窗口区域
  1198. let bigWinArea = {
  1199. width: width * scale,
  1200. height: height * scale,
  1201. left: sourceWin.centerX - rectArea.centerX * scale,
  1202. top: sourceWin.centerY - rectArea.centerY * scale
  1203. };
  1204. // 数据矫正
  1205. if (bigWinArea.left > 0) {
  1206. bigWinArea.left = 0;
  1207. }
  1208. if (bigWinArea.left < sourceWin.width - bigWinArea.width) {
  1209. bigWinArea.left = sourceWin.width - bigWinArea.width;
  1210. }
  1211. if (bigWinArea.top > 0) {
  1212. bigWinArea.top = 0;
  1213. }
  1214. if (bigWinArea.top < sourceWin.height - bigWinArea.height) {
  1215. bigWinArea.top = sourceWin.height - bigWinArea.height;
  1216. }
  1217. return bigWinArea;
  1218. }
  1219. /**
  1220. * @description 获取全屏状态
  1221. */
  1222. function getFull() {
  1223. return window.top.document.mozFullScreen || window.top.document.webkitIsFullScreen || window.top.document.msFullscreenElement;
  1224. }
  1225. /**
  1226. * @description 全屏状态改变的回调事件
  1227. */
  1228. function fullscreenchange() {
  1229. if (getFull()) {
  1230. return;
  1231. } else {
  1232. exitfullScreen();
  1233. }
  1234. }
  1235. /**
  1236. * @description 设置全屏
  1237. */
  1238. function setfullScreen() {
  1239. let docElm = window.top.document.documentElement;
  1240. if (docElm.requestFullScreen) {
  1241. docElm.requestFullScreen();
  1242. } else if (docElm.mozRequestFullScreen) {
  1243. docElm.mozRequestFullScreen();
  1244. } else if (docElm.webkitRequestFullScreen) {
  1245. docElm.webkitRequestFullScreen();
  1246. } else if (docElm.msRequestFullscreen) {
  1247. docElm.msRequestFullscreen();
  1248. }
  1249. handleFullscreen(true);
  1250. }
  1251. /**
  1252. * @description 退出全屏
  1253. */
  1254. function exitfullScreen() {
  1255. let docElm = window.top.document.documentElement;
  1256. if (docElm.exitFullscreen) {
  1257. docElm.exitFullscreen();
  1258. } else if (docElm.mozCancelFullScreen) {
  1259. docElm.mozCancelFullScreen();
  1260. } else if (docElm.webkitCancelFullScreen) {
  1261. docElm.webkitCancelFullScreen();
  1262. } else if (docElm.msExitFullscreen) {
  1263. docElm.msExitFullscreen();
  1264. }
  1265. handleFullscreen(false);
  1266. }
  1267. /**
  1268. * @description 处理全屏开关时的窗口大小
  1269. * @param {boolean} bool 是否要全屏
  1270. */
  1271. function handleFullscreen(bool) {
  1272. if (bool) {
  1273. let wrap = {
  1274. position: 'absolute',
  1275. left: 0,
  1276. top: 0,
  1277. width: window.screen.width + 'px',
  1278. height: window.screen.height + 'px',
  1279. overflow: 'visible'
  1280. }
  1281. setStyle($video_wrap, wrap);
  1282. } else {
  1283. let wrap = {
  1284. position: 'relative',
  1285. overflow: 'hidden',
  1286. width:'500px',
  1287. height: '300px',
  1288. }
  1289. setStyle($video_wrap, wrap);
  1290. }
  1291. }
  1292. /**
  1293. * @description 查询录像
  1294. */
  1295. const onSearchRecord = async () => {
  1296. let allRecords = [];
  1297. let recordNums = 0;
  1298. let playChannel = $('#h5_playback_channel').value - 0;
  1299. let _dom = _doc.querySelector('.h5-menu-list li:nth-child('+(curDeviceIndex+1)+')');
  1300. let _ip = _dom.getAttribute('data-ip');
  1301. let _port = _dom.getAttribute('data-port');
  1302. let _name = _dom.getAttribute('data-user');
  1303. let _pswd = _dom.getAttribute('data-pswd');
  1304. playbackOptions = {
  1305. ip: _ip,
  1306. port: _port,
  1307. name: _name,
  1308. pswd: _pswd
  1309. }
  1310. const getMediaFile = (params) => {
  1311. return new Promise((resolve, reject) => {
  1312. /**
  1313. * RPC.MediaFileFind.instance 创建媒体文件查找实例
  1314. * @returns {Promise}
  1315. */
  1316. RPC.MediaFileFind.instance().then(json => {
  1317. let queryId = json.result;
  1318. /**
  1319. * RPC.MediaFileFind.findFile 设置查找条件,并判断是否存在文件
  1320. * @param {number} queryId 实例id
  1321. * @param {object} params condition参数
  1322. * @returns {Promise}
  1323. */
  1324. RPC.MediaFileFind.findFile(queryId, params).then(() => {
  1325. findNextFile(queryId).then(() => {
  1326. resolve(true);
  1327. }).catch((err) => {
  1328. reject(err);
  1329. });
  1330. }).catch((err) => {
  1331. reject(err);
  1332. });
  1333. }).catch((err) => {
  1334. reject(err);
  1335. });
  1336. });
  1337. }
  1338. const findNextFile = (queryId) => {
  1339. return new Promise((resolve, reject) => {
  1340. /**
  1341. * RPC.MediaFileFind.findNextFile 在指定条件基础上查询文件信息
  1342. * @param {number} queryId 实例
  1343. * @param {object} 需要查找的数目
  1344. * @returns {Promise}
  1345. */
  1346. RPC.MediaFileFind.findNextFile(queryId, { 'count': 13 }).then(data => {
  1347. if (Number.isInteger(data.found)) {
  1348. recordNums = recordNums + data.found;
  1349. allRecords = allRecords.concat([...data.infos]);
  1350. if (data.found === 13) {
  1351. findNextFile(queryId).then(() => {
  1352. resolve(true);
  1353. }).catch((err) => {
  1354. reject(err);
  1355. });
  1356. } else {
  1357. recordArr = [...allRecords];
  1358. updateInfos(recordArr.slice(0, lINENUMBER));
  1359. updatePages();
  1360. stopFind(queryId);
  1361. resolve(true);
  1362. }
  1363. } else {
  1364. stopFind(queryId);
  1365. resolve(true);
  1366. }
  1367. }).catch((err) => {
  1368. reject(err);
  1369. stopFind(queryId);
  1370. });
  1371. })
  1372. }
  1373. const stopFind = object => {
  1374. return new Promise((resolve, reject) => {
  1375. /**
  1376. * PC.MediaFileFind.close 结束查询
  1377. * @param {number} object 媒体文件查找实例ID
  1378. * @returns {Promise}
  1379. */
  1380. RPC.MediaFileFind.close(object).then(() => {
  1381. /**
  1382. * PC.MediaFileFind.destroy 销毁媒体文件查找实例
  1383. * @param {number} object 媒体文件查找实例ID
  1384. */
  1385. RPC.MediaFileFind.destroy(object);
  1386. resolve(true);
  1387. }).catch(() => {
  1388. reject();
  1389. }).finally(() => {
  1390. });
  1391. })
  1392. }
  1393. const updateInfos = (infos) => {
  1394. let table = _doc.querySelector('#h5_table tbody');
  1395. table.innerHTML = '';
  1396. for(let i = 0; i < infos.length; i++) {
  1397. let time = infos[i].StartTime + ' - ' + infos[i].EndTime; //<input type="button" class="h5-button" btn-for="onGoTime" value="GO!">
  1398. let size = Math.round(infos[i].Length / 1024);
  1399. let newRow = table.insertRow(-1);
  1400. newRow.innerHTML = `<td><input type="checkbox" id="h5_check_${i}"></td><td>${i+1}</td><td>${time}</td><td>${size}</td><td><span id="h5_curTime_${i}">--</span><span>/</span><span id="h5_totalTime_${i}">--</span><input type="text" id="h5_goTime_${i}" style="width: 50px;"><input type="button" class="h5-button" id="h5_button_go_${i}" value="GO!"></td>`;
  1401. }
  1402. _doc.querySelectorAll('[id^=h5_button_go_]').forEach(item => {
  1403. item.addEventListener('click', function(event) {
  1404. let id = item.getAttribute('id').split('_')[3] - 0;
  1405. onGoTime(id);
  1406. });
  1407. });
  1408. _doc.querySelectorAll('[id^=h5_check_]').forEach(function(item) {
  1409. item.addEventListener('click', function(event) {
  1410. event.stopPropagation();
  1411. if(event.target.checked) {
  1412. //渲染裁剪时间
  1413. let _index = event.target.getAttribute('id').split('_')[2] - 0;
  1414. let startTime = recordArr[_index].StartTime.split(' ').join('T');
  1415. let endTime = recordArr[_index].EndTime.split(' ').join('T');
  1416. if(startTime.split(':')[2] === '00') {
  1417. startTime = startTime.substr(0, startTime.length - 3);
  1418. }
  1419. if(endTime.split(':')[2] === '00') {
  1420. endTime = endTime.substr(0, endTime.length - 3);
  1421. }
  1422. $('#h5_cutStartTime').value = startTime;
  1423. $('#h5_cutEndTime').value = endTime;
  1424. _doc.querySelector('[btn-for=onStartCut]').setAttribute('cutIndex', _index);
  1425. }
  1426. });
  1427. });
  1428. _doc.querySelectorAll('#h5_table tbody tr').forEach(function(item) {
  1429. item.addEventListener('dblclick', function(event) {
  1430. event.stopPropagation();
  1431. if(event.target.nodeName === 'TD') {
  1432. let dom = event.target.parentNode.childNodes[1];
  1433. let value = dom.innerText - 1;
  1434. let url = recordArr[value].FilePath;
  1435. onPlayBack(url, value);
  1436. }
  1437. });
  1438. });
  1439. }
  1440. const updatePages = () => {
  1441. totalPage = Math.ceil(recordNums/lINENUMBER);
  1442. $('#h5_curPage').innerText = 1;
  1443. $('#h5_totalPage').innerText = totalPage;
  1444. }
  1445. let tmpDir = [];
  1446. try {
  1447. /**
  1448. * RPC.getDeviceAllInfo 获取存储信息
  1449. * @param {string} 'getDeviceAllInfo' 方法名
  1450. * @return {Promise}
  1451. */
  1452. tmpDir = await RPC.getDeviceAllInfo('getDeviceAllInfo');
  1453. } catch(e) {
  1454. console.log(e);
  1455. }
  1456. let dirs = null;
  1457. if (tmpDir.info && tmpDir.info.length > 1) {
  1458. dirs = 'All';
  1459. }else {
  1460. dirs = tmpDir.info && tmpDir.info[0] && tmpDir.info[0].Detail && tmpDir.info[0].Detail[0] && tmpDir.info[0].Detail[0].Path || '/mnt/sd';
  1461. }
  1462. let startTime = $('#h5_startTime').value.replace('T', ' ');
  1463. let endTime = $('#h5_endTime').value.replace('T', ' ');
  1464. if(startTime.split(' ')[1].split(':').length < 3) {
  1465. startTime = startTime + ':00';
  1466. }
  1467. if(endTime.split(' ')[1].split(':').length < 3) {
  1468. endTime = endTime + ':00';
  1469. }
  1470. let params = {
  1471. condition: {
  1472. Channel: playChannel,
  1473. Dirs: [dirs],
  1474. StartTime: startTime,
  1475. EndTime: endTime,
  1476. Flags: null,
  1477. Events: ['*'],
  1478. Types: ['dav']
  1479. }
  1480. };
  1481. getMediaFile(params).catch((err) => {
  1482. if (err && err.error && err.error.code === 285409409) {
  1483. alert(tl('com.SDEncryptPlaybackTip')); //回放功能需要确保SD卡经过设备认证
  1484. } else {
  1485. let table = _doc.querySelector('#h5_table tbody');
  1486. table.innerHTML = '';
  1487. $('#h5_curPage').innerText = 1;
  1488. $('#h5_totalPage').innerText = 1;
  1489. alert(tl('com.NoData')); //无数据
  1490. }
  1491. });
  1492. }
  1493. /**
  1494. * @description 勾选当前页的全部录像
  1495. */
  1496. const onCheckAll = () => {
  1497. let dom = $('#h5_checkAll');
  1498. let ele = _doc.querySelectorAll('[id^=h5_check_]');
  1499. let domChecked = dom.checked;
  1500. ele.forEach((item, index) => {
  1501. item.checked = domChecked;
  1502. })
  1503. }
  1504. /**
  1505. * @description 下载录像
  1506. */
  1507. const onDownload = async () => {
  1508. let ele = _doc.querySelectorAll('[id^=h5_check_]');
  1509. downList = [];
  1510. ele.forEach((item, index) => {
  1511. let _id = item.getAttribute('id').split('_')[2] - 0;
  1512. if(item.checked) {
  1513. recordArr[(curPage - 1) * lINENUMBER + _id].selfCheckIndex = _id;
  1514. downList.push(recordArr[(curPage - 1) * lINENUMBER + _id]);
  1515. }
  1516. });
  1517. downItemIndex = 0;
  1518. onStartDownload(downList[downItemIndex]);
  1519. }
  1520. /**
  1521. * @description 开始下载录像
  1522. * @param {object} item 录像信息
  1523. */
  1524. const onStartDownload = (item) => {
  1525. let _cutIndex;
  1526. if(item) {
  1527. _cutIndex = item.selfCheckIndex;
  1528. }
  1529. let cutPlayer = null;
  1530. let _dom = _doc.querySelector('.h5-menu-list li:nth-child(' + (curDeviceIndex + 1) + ')');
  1531. let ip = _dom.getAttribute('data-ip');
  1532. let port = Number(_dom.getAttribute('data-port'));
  1533. let username = _dom.getAttribute('data-user');
  1534. let password = _dom.getAttribute('data-pswd');
  1535. let url = recordArr[_cutIndex].FilePath;
  1536. let _rtspURL = 'rtsp://'+ ip +':' + port + '/' + url;
  1537. let optionsRecord = {
  1538. wsURL: 'ws://'+ ip +':' + port + '/rtspoverwebsocket',
  1539. rtspURL: _rtspURL,
  1540. username: username,
  1541. password: password,
  1542. isPrivateProtocol: false,
  1543. realm: RPC.realm,
  1544. speed: 16,
  1545. playback: true,
  1546. isDownLoad:true
  1547. }
  1548. cutPlayer = new PlayerControl(optionsRecord);
  1549. cutPlayer.on('WorkerReady',function(){
  1550. cutPlayer.connect();
  1551. });
  1552. cutPlayer.on('FileOver',function(){
  1553. cutPlayer.startCut(false);
  1554. isCuting = false;
  1555. $('#h5_down_process').innerText = '100%';
  1556. downItemIndex++;
  1557. if(downList[downItemIndex]) {
  1558. onStartDownload(downList[downItemIndex]);
  1559. }
  1560. });
  1561. cutPlayer.on('UpdateTimeStamp', function (e) {
  1562. let s1 = new Date(item.StartTime).getTime()/1000;
  1563. let e1 = new Date(item.EndTime).getTime()/1000;
  1564. let process = parseInt((1 - (e1 - e.timestamp) / (e1 - s1)) * 100);
  1565. $('#h5_down_process').innerText = (process > 100 ? 100 : process) + '%';
  1566. if((e.timestamp >= s1) && !isCuting) {
  1567. cutPlayer.startCut(true);
  1568. isCuting = true;
  1569. }
  1570. if((e.timestamp >= e1 ) && isCuting) {
  1571. cutPlayer.startCut(false);
  1572. isCuting = false;
  1573. $('#h5_down_process').innerText = '100%';
  1574. downItemIndex++;
  1575. if(downList[downItemIndex]) {
  1576. onStartDownload(downList[downItemIndex]);
  1577. }
  1578. }
  1579. });
  1580. cutPlayer.init($canvas, $video);
  1581. cutInstance[WndIndex] = cutPlayer;
  1582. }
  1583. /**
  1584. * @description 更新录像列表当前页
  1585. */
  1586. const updateTable = () => {
  1587. $('#h5_checkAll').checked = false;
  1588. $('#h5_curPage').innerText = curPage;
  1589. let table = _doc.querySelector('#h5_table tbody');
  1590. table.innerHTML = '';
  1591. let index = (curPage - 1 ) * lINENUMBER;
  1592. let infos = recordArr.slice(index, index + lINENUMBER);
  1593. for(let i = 0; i < infos.length; i++) {
  1594. let time = infos[i].StartTime + '-' + infos[i].EndTime;
  1595. let size = Math.round(infos[i].Length / 1024) + '(KB)';
  1596. let newRow = table.insertRow(-1);
  1597. newRow.innerHTML = `<td><input type="checkbox" id="h5_check_${i}"></td><td>${index + i+1}</td><td>${time}</td><td>${size}</td><td><span id="h5_curTime_${i}">--</span><span>/</span><span id="h5_totalTime_${i}">--</span><input type="text" id="h5_goTime_${i}" style="width: 50px;"><input type="button" class="h5-button" id="h5_button_go_${i}" value="GO!"></td>`;
  1598. }
  1599. _doc.querySelectorAll('[id^=h5_check_]').forEach(function(item) {
  1600. item.addEventListener('click', function(event) {
  1601. event.stopPropagation();
  1602. if(event.target.checked) {
  1603. //渲染裁剪时间
  1604. let pageToIndex = (curPage - 1 ) * lINENUMBER;
  1605. let _index = event.target.getAttribute('id').split('_')[2] - 0 + pageToIndex;
  1606. let startTime = recordArr[_index].StartTime;
  1607. let endTime = recordArr[_index].EndTime;
  1608. $('#h5_cutStartTime').value = startTime;
  1609. $('#h5_cutEndTime').value = endTime;
  1610. _doc.querySelector('[btn-for=onStartCut]').setAttribute('cutIndex', _index);
  1611. }
  1612. });
  1613. });
  1614. _doc.querySelectorAll('#h5_table tbody tr').forEach(function(item) {
  1615. item.addEventListener('dblclick', function(event) {
  1616. event.stopPropagation();
  1617. let dom = event.target.parentNode.childNodes[1];
  1618. let value = dom.innerText - 1;
  1619. let url = recordArr[value].FilePath;
  1620. onPlayBack(url, value);
  1621. });
  1622. });
  1623. _doc.querySelectorAll('[id^=h5_button_go_]').forEach(item => {
  1624. item.addEventListener('click', function(event) {
  1625. event.stopPropagation();
  1626. let id = item.getAttribute('id').split('_')[3] - 0;
  1627. onGoTime(id);
  1628. });
  1629. });
  1630. }
  1631. /**
  1632. * @description 暂停回放
  1633. */
  1634. const onPausePlayback = () => {
  1635. if(playerInstance[WndIndex]) {
  1636. playerInstance[WndIndex].pause();
  1637. }
  1638. }
  1639. /**
  1640. * @description 继续回放
  1641. */
  1642. const onContinuePlayback = () => {
  1643. if(playerInstance[WndIndex]) {
  1644. playerInstance[WndIndex].play();
  1645. }
  1646. }
  1647. /**
  1648. * @description 停止回放
  1649. */
  1650. const onClosePlayback = () => {
  1651. if(playerInstance[WndIndex]) {
  1652. playerInstance[WndIndex].stop();
  1653. playerInstance[WndIndex].close();
  1654. playerInstance[WndIndex] = null;
  1655. let dom = $canvas;
  1656. if (dom.style.display === 'none') {
  1657. dom = $video;
  1658. }
  1659. dom.style.display = 'none';
  1660. }
  1661. }
  1662. /**
  1663. * @description 录像跳到指定时间
  1664. * @param 要跳转时间的录像的id
  1665. */
  1666. const onGoTime = (id) => {
  1667. let curTime = $('#h5_goTime_'+id).value - 0;
  1668. if(playerInstance[WndIndex]) {
  1669. playerInstance[WndIndex].playByTime(curTime);
  1670. }
  1671. }
  1672. /**
  1673. * @description ptz云台事件
  1674. * @param {string} type 云台事件类型
  1675. * @param {boolean} isStop 是否停止相应事件
  1676. */
  1677. window.onHandlePTZ = function(type, isStop) {
  1678. let _realDevice = _doc.querySelector('div[wnd-index="'+WndIndex+'"]').getAttribute('deviceindex');
  1679. if(_realDevice === null) {
  1680. return;
  1681. }
  1682. let _session = deviceObject.session[curDeviceIndex];
  1683. _setSession(_session);
  1684. let stepVal = $('#h5_ptz_step').value - 0;
  1685. let arg2 = 0;
  1686. let arg2Arr = ['LeftUp', 'RightUp', 'LeftDown', 'RightDown'];
  1687. let presetArr = ['GotoPreset','SetPreset', 'ClearPreset'];
  1688. let presetNum = $('#h5_preset').value - 0;
  1689. if(arg2Arr.indexOf(type) > -1) {
  1690. arg2 = stepVal;
  1691. }
  1692. if(!isStop) {
  1693. if(presetArr.indexOf(type) > -1) {
  1694. /**
  1695. * RPC.PTZManager 云台相关
  1696. * @param {string} 方法
  1697. * @param {number} channel 通道
  1698. * @param {object} 参数集合
  1699. */
  1700. RPC.PTZManager('start', channel, { 'code': type, 'arg1': presetNum, 'arg2': 0, 'arg3': 0 });
  1701. } else {
  1702. RPC.PTZManager('start', channel, { 'code': type, 'arg1': stepVal, 'arg2': arg2, 'arg3': 0 });
  1703. }
  1704. } else {
  1705. RPC.PTZManager('stop', channel, { 'code': type, 'arg1': stepVal, 'arg2': arg2, 'arg3': 0 });
  1706. }
  1707. };
  1708. //进入页面自动初始化
  1709. init();
  1710. }
  1711. document.querySelector('#device_ipc_tab').click();
  1712. /*
  1713. * 加载翻译
  1714. */
  1715. const languageTrans = () => {
  1716. fetch('./lang/' + curLang + '.txt')
  1717. .then(res => {
  1718. return res.json()
  1719. }).then(text => {
  1720. setLanguage(JSON.parse(JSON.stringify(text)));
  1721. translation();
  1722. });
  1723. }
  1724. languageTrans();
  1725. window.onload = function() {
  1726. if (!['http:', 'https:'].includes(window.location.protocol)) {
  1727. confirm('请参考readme.txt,在https server中打开此页面');
  1728. try {
  1729. window.close();
  1730. } catch (e) {
  1731. alert('请手动关闭此标签页');
  1732. }
  1733. }
  1734. };