index.vue 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450
  1. <template>
  2. <div class="app-container" style="height: 100%">
  3. <el-row v-if="toLivePreview===true" style="display: flex; width: 100%;height: 100%">
  4. <!--设备树-->
  5. <div class="tree-card" style="width: 220px">
  6. <div>
  7. <el-input v-model="searchWord" placeholder="请输入设备名称" clearable size="small"
  8. prefix-icon="el-icon-search"
  9. style="margin-bottom: 5px"
  10. />
  11. </div>
  12. <div class="head-container">
  13. <el-tabs v-model="activeName" @tab-click="handleTabClick" :stretch="true">
  14. <el-tab-pane label="摄像机" name="first">
  15. <el-tree :data="equipmentOptions" :props="defaultProps" node-key="id" :expand-on-click-node="true"
  16. ref="tree1" :filter-node-method="filterNode" default-expand-all highlight-current
  17. @node-click="handleNodeClick"
  18. >
  19. <span style="
  20. flex: 1;
  21. display: flex;
  22. align-items: center;
  23. justify-content: space-between;
  24. font-size: 14px;
  25. " @dblclick="handleNodedbClick(data)" slot-scope="{ node, data }"
  26. >
  27. <el-row :gutter="10" :id="data.id" style="
  28. display: flex;
  29. align-items: center;
  30. justify-content: center;
  31. width: 100%;
  32. height: 100%;
  33. "
  34. >
  35. <el-col :span="4" v-if="node.isLeaf">
  36. <i v-if="
  37. onlinePresenceList.find((item) => item.id === data.id)
  38. .onlinePresence === '1'
  39. " class="el-icon-video-camera" style="
  40. font-size: 26px;
  41. display: inline-flex;
  42. color: green;
  43. "
  44. ></i>
  45. <i v-else class="el-icon-video-camera" style="
  46. font-size: 26px;
  47. display: inline-flex;
  48. color: #6E7A89;
  49. "
  50. ></i>
  51. </el-col>
  52. <el-col :span="20">
  53. <el-row>
  54. <!-- <el-tooltip :content="data.label" placement="top">-->
  55. <span style="font-size: 14px; margin-left: 5px;font-weight: normal;
  56. width: 150px;
  57. display: inline-block;
  58. white-space: nowrap;
  59. overflow: hidden;
  60. text-overflow: ellipsis;">{{
  61. data.label
  62. }}</span>
  63. <!-- </el-tooltip>-->
  64. <!-- <span style="font-size: 16px;font-weight: normal">{{ data.label }}</span>-->
  65. </el-row>
  66. </el-col>
  67. </el-row>
  68. </span>
  69. </el-tree>
  70. </el-tab-pane>
  71. <el-tab-pane label="分组" name="second">
  72. <el-tree :data="groupOptions" :props="defaultProps" node-key="id" :expand-on-click-node="true"
  73. ref="tree2" :filter-node-method="filterNode" default-expand-all highlight-current
  74. @node-click="handleNodeClick"
  75. >
  76. <span style="
  77. margin-left: -15px;
  78. flex: 1;
  79. display: flex;
  80. align-items: center;
  81. justify-content: space-between;
  82. font-size: 14px;
  83. " @dblclick="handleNodedbClick(data)" slot-scope="{ node, data }"
  84. >
  85. <el-row :gutter="10" :id="'group' + data.id" style="
  86. display: flex;
  87. align-items: center;
  88. justify-content: center;
  89. width: 100%;
  90. height: 100%;
  91. "
  92. >
  93. <el-col :span="4" v-if="data.isLeaf">
  94. <i v-if="
  95. onlinePresenceList.find((item) => item.id === data.id)
  96. .onlinePresence === '1'
  97. " class="el-icon-video-camera" style="
  98. font-size: 26px;
  99. display: inline-flex;
  100. color: green;
  101. "
  102. ></i>
  103. <i v-else class="el-icon-video-camera" style="
  104. font-size: 26px;
  105. display: inline-flex;
  106. color: #6E7A89;
  107. "
  108. ></i>
  109. </el-col>
  110. <el-col :span="20">
  111. <el-row>
  112. <!-- <span style="font-size: 16px;font-weight: normal">{{ data.label }}</span>-->
  113. <!-- <el-tooltip :content="data.label" placement="top">-->
  114. <span style="font-size: 14px; margin-left: 5px;font-weight: normal;
  115. width: 140px;
  116. display: inline-block;
  117. white-space: nowrap;
  118. overflow: hidden;
  119. text-overflow: ellipsis;">{{
  120. data.label
  121. }}</span>
  122. <!-- </el-tooltip>-->
  123. </el-row>
  124. </el-col>
  125. </el-row>
  126. </span>
  127. </el-tree>
  128. </el-tab-pane>
  129. <el-tab-pane label="视图" name="third">
  130. <el-tree :data="viewOptions" :props="defaultProps" :expand-on-click-node="true" ref="tree3"
  131. :filter-node-method="filterNode" default-expand-all highlight-current
  132. @node-click="handleViewNodeClick"
  133. >
  134. <span style="
  135. flex: 1;
  136. display: flex;
  137. align-items: center;
  138. justify-content: space-between;
  139. font-size: 14px;
  140. " @dblclick="handleViewNodedbClick(data)" slot-scope="{ node, data }"
  141. >
  142. <div style="display: flex; align-items: center">
  143. <v-icon name="md-preview-sharp" scale="1.2" fill="#ffffff"></v-icon>
  144. <!-- <span style="font-size: 18px; margin-left: 5px;font-weight: normal">{{-->
  145. <!-- data.label-->
  146. <!-- }}</span>-->
  147. <!-- <el-tooltip :content="data.label" placement="top">-->
  148. <span style="font-size: 14px; margin-left: 5px;font-weight: normal;
  149. width:120px;
  150. display: inline-block;
  151. white-space: nowrap;
  152. overflow: hidden;
  153. text-overflow: ellipsis;">{{
  154. data.label
  155. }}</span>
  156. <!-- </el-tooltip>-->
  157. </div>
  158. <span v-if="data.isLeaf" style="margin-right: 10px">
  159. <el-dropdown size="mini" trigger="click">
  160. <i class="el-icon-more" style="color: #ffffff; font-size: 20px"></i>
  161. <el-dropdown-menu slot="dropdown">
  162. <el-dropdown-item icon="el-icon-edit" @click.native="openUpdateView = true">
  163. 编辑
  164. </el-dropdown-item>
  165. <el-dropdown-item icon="el-icon-delete" @click.native="deleteView(data)">
  166. 删除</el-dropdown-item>
  167. </el-dropdown-menu>
  168. </el-dropdown>
  169. </span>
  170. </span>
  171. </el-tree>
  172. </el-tab-pane>
  173. </el-tabs>
  174. </div>
  175. <div class="tool-tab">
  176. <el-tabs v-model="activeTool" :stretch="true">
  177. <el-tab-pane label="工具" name="first">
  178. <div style="
  179. display: flex;
  180. flex-direction: row;
  181. flex-wrap: wrap;
  182. justify-content: space-around;
  183. "
  184. >
  185. <div class="fast-button" @click="openSave = true">
  186. 保存当前视图
  187. </div>
  188. <!-- <div class="fast-button" v-if="activeName === 'third' && viewId" @click="beforeShare">分享当前视图
  189. </div> -->
  190. <div class="fast-button" @click="fisheye" v-if="equipmentInfo.isFishEye === '1'">
  191. 切换显示模式
  192. </div>
  193. </div>
  194. </el-tab-pane>
  195. <el-tab-pane label="灯光" v-if="
  196. equipmentInfo.isOutboard === '1' &&
  197. equipmentInfo.isLamplight === '1'
  198. "
  199. >
  200. <div style="
  201. display: flex;
  202. flex-direction: column;
  203. align-items: baseline;
  204. "
  205. >
  206. <el-switch
  207. style="color: #ffffff; zoom: 1.15; margin-top: 5px" v-model="equipmentInfo.lamplightStatus"
  208. inactive-text="开启灯光" active-value="1" inactive-value="0" @change="handleOpenLight"
  209. />
  210. <div style="
  211. display: flex;
  212. justify-content: left;
  213. align-items: center;
  214. width: 100%;
  215. margin-top: 5px;
  216. "
  217. >
  218. <span style="font-size: 16px; color: #ffffff; width: 70px">亮度调节</span>
  219. <el-slider v-loading.fullscreen.lock="fullscreenLoading"
  220. element-loading-text="命令执行中"
  221. element-loading-spinner="el-icon-loading" style="width: 60%; margin-right: 10px; margin-left: 10px" v-model="equipmentInfo.light"
  222. :step="20" :min="20" @change="changeLight" show-stops
  223. ></el-slider>
  224. </div>
  225. <div class="device-info">
  226. <el-row type="flex" justify="space-around">
  227. <el-col :span="8" class="info-item">
  228. <div :class="[
  229. 'status-light',
  230. newEquipmentInfo.overallSwitch ? 'active' : 'inactive',
  231. ]"
  232. ></div>
  233. <span>总控</span>
  234. </el-col>
  235. <el-col v-if="!this.equipmentInfo.isGeneralControl" :span="8" class="info-item">
  236. <div :class="[
  237. 'status-light',
  238. newEquipmentInfo.moduleSwitch ? 'active' : 'inactive',
  239. ]"
  240. ></div>
  241. <span>分控</span>
  242. </el-col>
  243. <el-col :span="8" class="info-item">
  244. <div :class="[
  245. 'status-light',
  246. newEquipmentInfo.lightSwitch ? 'active' : 'inactive',
  247. ]"
  248. ></div>
  249. <span>照明灯</span>
  250. </el-col>
  251. </el-row>
  252. </div>
  253. </div>
  254. </el-tab-pane>
  255. <el-tab-pane v-if="
  256. equipmentInfo.isGimbalControl === '1' &&
  257. equipmentInfo.isHolder === '1'
  258. " label="云台"
  259. >
  260. <div class="operate-panel" @dragstart.prevent>
  261. <div class="move-btn">
  262. <div class="btn1" style="margin:45px 0 0 40px">
  263. <img :src="leftUpIcon" class="btn" style="cursor: pointer"
  264. @mousedown="handleMove('leftUp')" @mouseup="handleMove('stop')"
  265. @mouseenter="handleMove('leftUpEnter')" @mouseleave="handleMove('leave')">
  266. <!-- <i :class="leftUpIcon?'btn el-icon-arrow-up':'btn el-icon-arrow-down'" style="transform: rotate(-45deg); cursor: pointer"-->
  267. <!-- @mousedown="handleMove('leftUp')" @mouseup="handleMove('stop')"-->
  268. <!-- />-->
  269. </div>
  270. <div class="btn1" style="margin-bottom: 5px;margin-left: -20px; cursor: pointer">
  271. <!-- <i class="btn el-icon-arrow-down" @mousedown="handleMove('up')" @mouseup="handleMove('stop')"/>-->
  272. <img :src="upIcon" class="btn" style="cursor: pointer;height: 27px"
  273. @mousedown="handleMove('up')" @mouseup="handleMove('stop')"
  274. @mouseenter="handleMove('upEnter')" @mouseleave="handleMove('leave')">
  275. </div>
  276. <div class="btn1" style="margin-top: 45px;margin-left: -25px">
  277. <!-- <i class="btn el-icon-arrow-up" style="transform: rotate(45deg); cursor: pointer"-->
  278. <!-- @mousedown="handleMove('rightUp')" @mouseup="handleMove('stop')"-->
  279. <!-- />-->
  280. <img :src="rightUpIcon" class="btn" style="cursor: pointer;transform: rotate(15deg)"
  281. @mousedown="handleMove('rightUp')" @mouseup="handleMove('stop')"
  282. @mouseenter="handleMove('rightUpEnter')" @mouseleave="handleMove('leave')">
  283. </div>
  284. <div class="btn1" style="margin-left: 23px;margin-top: 5px">
  285. <!-- <i class="btn el-icon-arrow-up" style="transform: rotate(-90deg); cursor: pointer"-->
  286. <!-- @mousedown="handleMove('left')" @mouseup="handleMove('stop')"-->
  287. <!-- />-->
  288. <img :src="leftIcon" class="btn" style="cursor: pointer;width: 27px"
  289. @mousedown="handleMove('left')" @mouseup="handleMove('stop')"
  290. @mouseenter="handleMove('leftEnter')" @mouseleave="handleMove('leave')">
  291. </div>
  292. <!-- <div class="btn" style="">-->
  293. <!-- <i class="btn el-icon-refresh" @click="handleMove('refresh')"/>-->
  294. <!-- </div>-->
  295. <div style="margin-top:5px;margin-left: 70px;width: 40px;height: 35px">
  296. <!-- <i class="btn el-icon-arrow-up" style="transform: rotate(90deg); cursor: pointer"-->
  297. <!-- @mousedown="handleMove('right')" @mouseup="handleMove('stop')"-->
  298. <!-- />-->
  299. <img :src="rightIcon" class="btn" style="cursor: pointer;width: 27px"
  300. @mousedown="handleMove('right')" @mouseup="handleMove('stop')"
  301. @mouseenter="handleMove('rightEnter')" @mouseleave="handleMove('leave')">
  302. </div>
  303. <div class="btn1" style="margin-bottom: 35px;margin-left: 45px">
  304. <!-- <i class="btn el-icon-arrow-up" style="transform: rotate(225deg); cursor: pointer"-->
  305. <!-- @mousedown="handleMove('leftDown')" @mouseup="handleMove('stop')"-->
  306. <!-- />-->
  307. <img :src="leftDownIcon" class="btn" style="cursor: pointer"
  308. @mousedown="handleMove('leftDown')" @mouseup="handleMove('stop')"
  309. @mouseenter="handleMove('leftDownEnter')" @mouseleave="handleMove('leave')">
  310. </div>
  311. <div class="btn1" style="margin-top: 20px;margin-left: -20px">
  312. <!-- <i class="btn el-icon-arrow-up" style="transform: rotate(180deg); cursor: pointer"-->
  313. <!-- @mousedown="handleMove('down')" @mouseup="handleMove('stop')"-->
  314. <!-- />-->
  315. <img :src="downIcon" class="btn" style="cursor: pointer;height: 27px"
  316. @mousedown="handleMove('down')" @mouseup="handleMove('stop')"
  317. @mouseenter="handleMove('downEnter')" @mouseleave="handleMove('leave')">
  318. </div>
  319. <div class="btn1" style="margin-left: -20px;margin-bottom: 40px">
  320. <!-- <i class="btn el-icon-arrow-up" style="transform: rotate(135deg); cursor: pointer"-->
  321. <!-- @mousedown="handleMove('rightDown')" @mouseup="handleMove('stop')"-->
  322. <!-- />-->
  323. <img :src="rightDownIcon" class="btn" style="cursor: pointer"
  324. @mousedown="handleMove('rightDown')" @mouseup="handleMove('stop')"
  325. @mouseenter="handleMove('rightDownEnter')" @mouseleave="handleMove('leave')">
  326. </div>
  327. </div>
  328. <div class="compose-btn">
  329. <div style="width: 50%;float: left">
  330. <div class="div-class">
  331. <div class="span-class" >变倍</div>
  332. </div>
  333. <div class="div-class">
  334. <img :src="double" alt="倍加" style="width: 35px;height: 35px;margin-top: 3px"
  335. @mousedown="handleFocusing('up')" @mouseup="handleFocusing('stop')"
  336. @mouseenter="handleFocusing('upEnter')" @mouseleave="handleFocusing('leave')">
  337. </div>
  338. </div>
  339. <div style="width: 50%;float: left">
  340. <div class="div-class">
  341. <div class="span-class" >变倍</div>
  342. </div>
  343. <div class="div-class">
  344. <img :src="subtract" alt="倍减" style="width: 35px;height: 35px;margin-top: 3px"
  345. @mousedown="handleFocusing('down')" @mouseup="handleFocusing('stop')"
  346. @mouseenter="handleFocusing('downEnter')" @mouseleave="handleFocusing('leave')">
  347. </div>
  348. </div>
  349. <!-- <div style="width: 50%;float: left">-->
  350. <!-- <div class="div-class">-->
  351. <!-- <div class="span-class" >变焦</div>-->
  352. <!-- </div>-->
  353. <!-- <div class="div-class">-->
  354. <!-- <img :src="double1" alt="倍加" style="width: 35px;height: 35px;margin-top: 3px"-->
  355. <!-- @mousedown="handleFocusing('focusOut')" @mouseup="handleFocusing('stop')"-->
  356. <!-- @mouseenter="handleFocusing('focusOutEnter')" @mouseleave="handleFocusing('leave')">-->
  357. <!-- </div>-->
  358. <!-- </div>-->
  359. <!-- <div style="width: 50%;float: left">-->
  360. <!-- <div class="div-class">-->
  361. <!-- <div class="span-class" >变焦</div>-->
  362. <!-- </div>-->
  363. <!-- <div class="div-class">-->
  364. <!-- <img :src="subtract1" alt="倍减" style="width: 35px;height: 35px;margin-top: 3px"-->
  365. <!-- @mousedown="handleFocusing('focusIn')" @mouseup="handleFocusing('stop')"-->
  366. <!-- @mouseenter="handleFocusing('focusInEnter')" @mouseleave="handleFocusing('leave')">-->
  367. <!-- </div>-->
  368. <!-- </div>-->
  369. <div style="width: 100%;margin-top: 65px">
  370. <div class="span-class1">速度</div>
  371. <el-slider :min="0.2" :max="1" v-model="speed" :step="0.2" show-stops style="float: left;width: 43%;margin:0 10px"></el-slider>
  372. <div class="span-class1">{{speed}}</div>
  373. </div>
  374. <!-- <div class="btn2">-->
  375. <!-- <i class="el-icon-zoom-in" style="cursor: pointer" @click="addSpeed()"></i>-->
  376. <!-- <div style="display: flex">速度:{{ getSpeed }}</div>-->
  377. <!-- <i class="el-icon-zoom-out" style="cursor: pointer" @click="delSpeed()"></i>-->
  378. <!-- </div>-->
  379. <!-- <div class="btn2">-->
  380. <!-- <i class="el-icon-zoom-in" style="cursor: pointer" @mousedown="handleFocusing('up')"-->
  381. <!-- @mouseup="handleFocusing('stop')"-->
  382. <!-- ></i>-->
  383. <!-- <span>变倍</span>-->
  384. <!-- <i class="el-icon-zoom-out" style="cursor: pointer" @mousedown="handleFocusing('down')"-->
  385. <!-- @mouseup="handleFocusing('stop')"-->
  386. <!-- ></i>-->
  387. <!-- </div>-->
  388. <!-- <div class="btn2">-->
  389. <!-- <i class="el-icon-zoom-in" style="cursor: pointer" @mousedown="handleFocusing('focusOut')"-->
  390. <!-- @mouseup="handleFocusing('stop')"-->
  391. <!-- ></i>-->
  392. <!-- <span>变焦</span>-->
  393. <!-- <i class="el-icon-zoom-out" style="cursor: pointer" @mousedown="handleFocusing('focusIn')"-->
  394. <!-- @mouseup="handleFocusing('stop')"-->
  395. <!-- ></i>-->
  396. <!-- </div>-->
  397. </div>
  398. </div>
  399. </el-tab-pane>
  400. </el-tabs>
  401. </div>
  402. </div>
  403. <!--监控预览-->
  404. <div class="tree-card" style="flex: 1; margin-left: 5px; flex-direction: column-reverse">
  405. <toolbar style="height: 45px" ref="toolbar" @startPolling="startPolling" @endPolling="endPolling"></toolbar>
  406. <div style="
  407. display: flex;
  408. align-items: flex-start;
  409. justify-content: center;
  410. flex: 1;
  411. overflow: hidden;
  412. margin-left: 5px;
  413. "
  414. >
  415. <div style="height: 100%;width: 99.9%; aspect-ratio: 16/9;">
  416. <videoBox ref="video" @clearTreeSelected="clearTreeSelected" @setCurrentKeyTree="setCurrentKeyTree"
  417. @clickToolBar="clickToolBar"
  418. ></videoBox>
  419. </div>
  420. </div>
  421. </div>
  422. <el-dialog title="保存视图" :visible.sync="openSave" width="300px" append-to-body>
  423. <el-row type="flex" justify="center">
  424. <el-input v-model="viewName" placeholder="请输入视图名称"></el-input>
  425. </el-row>
  426. <div slot="footer" class="dialog-footer">
  427. <el-button size="small" @click="openSave = false">取消</el-button>
  428. <el-button size="small" type="primary" @click="save">确定</el-button>
  429. </div>
  430. </el-dialog>
  431. <el-dialog title="修改视图" :visible.sync="openUpdateView" width="300px" append-to-body>
  432. <el-row type="flex" justify="center">
  433. <el-input v-model="viewName" placeholder="请输入视图名称"></el-input>
  434. </el-row>
  435. <div slot="footer" class="dialog-footer">
  436. <el-button size="small" @click="openUpdateView = false">取消</el-button>
  437. <el-button size="small" type="primary" @click="updateView">确定</el-button>
  438. </div>
  439. </el-dialog>
  440. <el-dialog title="分享视图" :visible.sync="openShare" width="600px" append-to-body>
  441. <el-row type="flex" justify="center">
  442. <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
  443. <el-table-column type="selection" width="50" align="center"/>
  444. <el-table-column label="用户编号" align="center" key="userId" prop="userId"/>
  445. <el-table-column label="用户名称" align="center" key="userName" prop="userName"
  446. :show-overflow-tooltip="true"
  447. />
  448. <el-table-column label="用户昵称" align="center" key="nickName" prop="nickName"
  449. :show-overflow-tooltip="true"
  450. />
  451. <el-table-column label="部门" align="center" key="deptName" prop="dept.deptName"
  452. :show-overflow-tooltip="true"
  453. />
  454. </el-table>
  455. </el-row>
  456. <div slot="footer" class="dialog-footer">
  457. <el-button size="small" @click="openShare = false">取消</el-button>
  458. <el-button size="small" type="primary" @click="share">确定</el-button>
  459. </div>
  460. </el-dialog>
  461. </el-row>
  462. <big-video-playback v-else-if="toVideoPlayback===true" :stream-options="streamOptions"></big-video-playback>
  463. <div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}" v-else>
  464. <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
  465. <sidebar v-if="!sidebar.hide" class="sidebar-container"/>
  466. <div :class="{hasTagsView:needTagsView,sidebarHide:sidebar.hide}" class="main-container">
  467. <div :class="{'fixed-header':fixedHeader}">
  468. <navbar/>
  469. <tags-view v-if="needTagsView"/>
  470. </div>
  471. <app-main/>
  472. <right-panel>
  473. <settings/>
  474. </right-panel>
  475. </div>
  476. </div>
  477. </div>
  478. <!-- <div lass="app-container">-->
  479. <!---->
  480. <!-- </div>-->
  481. </template>
  482. <script>
  483. import RightPanel from '@/components/RightPanel'
  484. import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
  485. import ResizeMixin from './mixin/ResizeHandler'
  486. import { mapGetters, mapState } from 'vuex'
  487. import variables from '@/assets/styles/variables.scss'
  488. import BigLivePreview from '@/views/livePreview/bigLivePreview.vue'
  489. import { isRelogin } from '@/utils/request'
  490. import Cookies from 'js-cookie'
  491. import { login } from '@/api/login'
  492. import { getToken, setToken } from '@/utils/auth'
  493. import store from '@/store'
  494. import NProgress from 'nprogress'
  495. import toolbar from '@/views/livePreview/components/toolBar1.vue'
  496. import videoBox from '@/views/livePreview/components/videoBox1.vue'
  497. import { cameraSelect, listCamera } from '@/api/equipment/camera'
  498. import { cameraGroupSelect } from '@/api/equipment/group'
  499. import { deletePreview, savePreview, selectViewList, sharePreview, updatePreview } from '@/api/livePreview'
  500. import { lamplightInfo } from '@/api/equipment/lamplight'
  501. import { listUser } from '@/api/system/user'
  502. import { dim, power } from '@/api/outBoard/keyControl'
  503. import {
  504. downFocalLength, focusIn, focusOut,
  505. leftDown,
  506. leftUp,
  507. rightDown,
  508. rightUp,
  509. shotDown,
  510. shotLeft,
  511. shotRight,
  512. shotUp,
  513. stopMove, upFocalLength
  514. } from '@/api/livePreview/monitor'
  515. import BigVideoPlayback from '@/views/videoPlayback/bigVideoPlayback.vue'
  516. import leftUpImg from '../assets/images/ptz_btn_left_up.png'
  517. import leftUpImg1 from '../assets/images/ptz_btn_left_up1.png'
  518. import upImg from '../assets/images/ptz_btn_up.png'
  519. import upImg1 from '../assets/images/ptz_btn_up1.png'
  520. import rightUpImg from '../assets/images/ptz_btn_right_up.png'
  521. import rightUpImg1 from '../assets/images/ptz_btn_right_up1.png'
  522. import leftImg from '../assets/images/ptz_btn_left.png'
  523. import leftImg1 from '../assets/images/ptz_btn_left1.png'
  524. import rightImg from '../assets/images/ptz_btn_right.png'
  525. import rightImg1 from '../assets/images/ptz_btn_right1.png'
  526. import leftDownImg from '../assets/images/ptz_btn_left_down.png'
  527. import leftDownImg1 from '../assets/images/ptz_btn_left_down1.png'
  528. import downImg from '../assets/images/ptz_btn_down.png'
  529. import downImg1 from '../assets/images/ptz_btn_down1.png'
  530. import rightDownImg from '../assets/images/ptz_btn_right_down.png'
  531. import rightDownImg1 from '../assets/images/ptz_btn_right_down1.png'
  532. import doubleImg from '../assets/images/a5.png'
  533. import doubleImg1 from '../assets/images/a5-1.png'
  534. import subtractImg from '../assets/images/a6.png'
  535. import subtractImg1 from '../assets/images/a6-1.png'
  536. import kuang1 from '../assets/images/kuang-1.png'
  537. import kuang2 from '../assets/images/kuang-2.png'
  538. import { configPage } from '/public/config'
  539. import { selectStreamProxyItem } from '@/api/service/streamProxy'
  540. export default {
  541. name: 'Layout',
  542. components: {
  543. BigVideoPlayback,
  544. videoBox, toolbar,
  545. BigLivePreview,
  546. AppMain,
  547. Navbar,
  548. RightPanel,
  549. Settings,
  550. Sidebar,
  551. TagsView
  552. },
  553. data(){
  554. return {
  555. double:doubleImg,
  556. double1:doubleImg,
  557. subtract:subtractImg,
  558. subtract1:subtractImg,
  559. cellCount: 1, //分屏数
  560. speed: 0.4, //速度
  561. marks:{
  562. 0:'0',
  563. 0.2:'0.2',
  564. 0.4:'0.4',
  565. 0.6:'0.6',
  566. 0.8:'0.8',
  567. 1:'1',
  568. },
  569. userId: undefined,
  570. searchWord: '',
  571. activeName: 'first', //tab页
  572. activeTool: 'first',
  573. equipmentOptions: [],
  574. onlinePresenceList: [],
  575. groupOptions: [],
  576. viewOptions: [],
  577. defaultProps: {
  578. children: 'children',
  579. label: 'label'
  580. },
  581. equipmentInfo: {
  582. lamplightId: undefined,
  583. lamplightOnline: '',
  584. lamplightStatus: '',
  585. cameraName: '',
  586. light: '',
  587. lightSwitch: true,
  588. overallSwitch: true,
  589. moduleSwitch: true,
  590. id: '',
  591. app: '',
  592. isGeneralControl: true
  593. },
  594. newEquipmentInfo: {
  595. lamplightId: undefined,
  596. lamplightOnline: '',
  597. lamplightStatus: '',
  598. cameraName: '',
  599. light: '',
  600. lightSwitch: true,
  601. overallSwitch: true,
  602. moduleSwitch: true,
  603. id: '',
  604. app: '',
  605. isGeneralControl: true
  606. },
  607. viewId: undefined,
  608. viewName: '',
  609. openSave: false,
  610. loading: false,
  611. // 选中数组
  612. ids: [],
  613. // 非单个禁用
  614. single: true,
  615. // 非多个禁用
  616. multiple: true,
  617. userList: [],
  618. openShare: false,
  619. openSeize: false,
  620. seizeTime: undefined,
  621. selectedTree: [],
  622. //
  623. showLightCard: false,
  624. timer: null,
  625. cameraList: [],
  626. autoplay: false,
  627. interval: 10000,
  628. pollingInterval: null,
  629. openUpdateView: false,
  630. fishEyeType: '鱼眼',
  631. onlinePresenceInterval: null, //定时器id
  632. messages: [],
  633. eventSource: null,
  634. fullscreenLoading: false,
  635. loginForm: {
  636. username: "hfdz",
  637. password: "hfdz123",
  638. rememberMe: false,
  639. code: "",
  640. uuid: ""
  641. },
  642. toLivePreview:false,
  643. toVideoPlayback:false,
  644. leftUpIcon:leftUpImg,
  645. upIcon:upImg,
  646. rightUpIcon:rightUpImg,
  647. leftIcon:leftImg,
  648. rightIcon:rightImg,
  649. leftDownIcon:leftDownImg,
  650. downIcon:downImg,
  651. rightDownIcon:rightDownImg,
  652. streamOptions: [],
  653. }
  654. },
  655. mixins: [ResizeMixin],
  656. computed: {
  657. ...mapState({
  658. theme: state => state.settings.theme,
  659. sideTheme: state => state.settings.sideTheme,
  660. sidebar: state => state.app.sidebar,
  661. device: state => state.app.device,
  662. needTagsView: state => state.settings.tagsView,
  663. fixedHeader: state => state.settings.fixedHeader
  664. }),
  665. classObj() {
  666. return {
  667. hideSidebar: !this.sidebar.opened,
  668. openSidebar: this.sidebar.opened,
  669. withoutAnimation: this.sidebar.withoutAnimation,
  670. mobile: this.device === 'mobile'
  671. }
  672. },
  673. variables() {
  674. return variables;
  675. },
  676. ...mapGetters(['selectedTreeData', 'selectedMonitor', 'boxList', 'active']),
  677. getSpeed() {
  678. return this.speed.toFixed(1)
  679. }
  680. },
  681. watch: {
  682. // 根据名称筛选树
  683. searchWord(val) {
  684. switch (this.activeName) {
  685. case 'first':
  686. this.$refs.tree1.filter(val)
  687. return
  688. case 'second':
  689. this.$refs.tree2.filter(val)
  690. return
  691. case 'third':
  692. this.$refs.tree3.filter(val)
  693. return
  694. }
  695. }
  696. },
  697. created() {
  698. this.toLivePreview=false
  699. this.toVideoPlayback=false
  700. console.log(Cookies.get('Admin-Token'),2222)
  701. console.log(new URLSearchParams(window.location.search),"new URLSearchParams(window.location.search)")
  702. let toLivePreview=new URLSearchParams(window.location.search).get('toLivePreview')
  703. let toVideoPlayback=new URLSearchParams(window.location.search).get('toVideoPlayback')
  704. if(toVideoPlayback){
  705. this.toLivePreview=false
  706. this.toVideoPlayback=true
  707. }
  708. if(toLivePreview){
  709. this.toVideoPlayback=false
  710. this.toLivePreview = true;
  711. }
  712. console.log(toLivePreview,2222)
  713. console.log(toVideoPlayback==='true',2222)
  714. // 确保在token验证后再初始化预览
  715. if (toLivePreview||toVideoPlayback) {
  716. // 未登录则执行自动登录
  717. const autoLogin = async () => {
  718. try {
  719. const loginForm = {
  720. username: "hfdz",
  721. password: "hfdz123".split('').map(char => {
  722. const charCode = char.charCodeAt(0);
  723. return (charCode >= 32 && charCode <= 126)
  724. ? String.fromCharCode(32 + (charCode - 32 + 10) % 95)
  725. : char;
  726. }).join(''),
  727. rememberMe: false,
  728. code: "",
  729. uuid: ""
  730. };
  731. const res = await login(loginForm.username, loginForm.password, loginForm.code, loginForm.uuid);
  732. setToken(res.token)
  733. this.$nextTick(() => {
  734. // this.toLivePreview=false
  735. // this.toVideoPlayback=false
  736. console.log(getToken(),2222)
  737. if (getToken()) {
  738. store.dispatch('GetInfo').catch(err => console.error("用户信息获取失败", err));
  739. // if(toVideoPlayback){
  740. // this.toVideoPlayback=true
  741. // }
  742. // if(toLivePreview){
  743. // this.toLivePreview = true;
  744. // }
  745. this.initData();
  746. // this.login(); // 执行组件内的登录方法确保状态同步
  747. }
  748. });
  749. } catch (error) {
  750. console.error("自动登录失败", error);
  751. }
  752. };
  753. autoLogin();
  754. }
  755. this.userId = this.$store.getters.userId
  756. console.log(this.toLivePreview,777)
  757. },
  758. mounted() {
  759. // 启动在线轮询
  760. this.initSSE()
  761. },
  762. beforeDestroy() {
  763. // 在组件销毁之前清除定时器,防止内存泄漏
  764. this.closeSSE()
  765. this.toLivePreview=false
  766. this.toVideoPlayback=false
  767. },
  768. methods: {
  769. handleClickOutside() {
  770. this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
  771. },
  772. login(){
  773. let password = this.loginForm.password;
  774. this.loginForm.password = this.encrypt(this.loginForm.password, 10);
  775. this.$store.dispatch("Login", this.loginForm).then(() => {
  776. this.loginForm.password = password;
  777. console.log(123123)
  778. // this.$router.push({ path: this.redirect || "/" }).catch(() => { });
  779. // this.$router.push({ path: '/bigLivePreview' || "/" }).catch(() => { });
  780. }).catch(() => {
  781. this.loginForm.password = password;
  782. this.loading = false;
  783. if (this.captchaEnabled) {
  784. this.getCode();
  785. }
  786. });
  787. },
  788. // 加密方法
  789. encrypt(text, shift) {
  790. const ASCII_PRINTABLE_START = 32;
  791. const ASCII_PRINTABLE_END = 126;
  792. const ASCII_PRINTABLE_RANGE = ASCII_PRINTABLE_END - ASCII_PRINTABLE_START + 1;
  793. return text.split('').map(char => {
  794. let charCode = char.charCodeAt(0);
  795. if (charCode >= ASCII_PRINTABLE_START && charCode <= ASCII_PRINTABLE_END) {
  796. charCode = ASCII_PRINTABLE_START + (charCode - ASCII_PRINTABLE_START + shift) % ASCII_PRINTABLE_RANGE;
  797. }
  798. return String.fromCharCode(charCode);
  799. }).join('');
  800. },
  801. initData() {
  802. this.getEquipmentOptions();
  803. this.getGroupOptions();
  804. this.getViewOptions();
  805. this.initSSE();
  806. if(this.toVideoPlayback===true){
  807. this.getStreamOptions();
  808. }
  809. },
  810. getStreamOptions() {
  811. selectStreamProxyItem({ recordShow: '1' }).then((response) => {
  812. const children = response.data.map((item) => ({
  813. ...item,
  814. isLeaf: true,
  815. label: item.app,
  816. key: item.id,
  817. }));
  818. this.streamOptions = children;
  819. });
  820. },
  821. getEquipmentOptions() {
  822. cameraSelect().then((response) => {
  823. this.cameraList = response.rows
  824. const children = response.rows.map((item) => ({
  825. ...item,
  826. isLeaf: true,
  827. label: item.cameraName,
  828. key: item.id
  829. }))
  830. this.equipmentOptions = children
  831. this.onlinePresenceList = children
  832. })
  833. },
  834. getGroupOptions() {
  835. // 获取分组
  836. cameraGroupSelect().then((res) => {
  837. this.groupOptions = res.map((item) => ({
  838. ...item,
  839. children: [],
  840. isLeaf: false,
  841. label: item.groupName,
  842. key: item.id
  843. }))
  844. })
  845. },
  846. // 获取设备分组下的设备
  847. handleTabClick(tab) {
  848. if (tab.name === 'second') {
  849. this.groupOptions.forEach(function(item) {
  850. listCamera({ groupId: item.id }).then((res) => {
  851. const children = res.rows.map((item) => ({
  852. ...item,
  853. isLeaf: true,
  854. label: item.cameraName
  855. }))
  856. item.children = children
  857. })
  858. })
  859. }
  860. },
  861. getViewOptions() {
  862. selectViewList().then((response) => {
  863. // 去除item为空的项
  864. const children = response.data
  865. .filter((item) => item)
  866. .map((item) => ({
  867. ...item,
  868. isLeaf: true,
  869. label: item.viewName,
  870. key: item.id
  871. }))
  872. this.viewOptions = children
  873. })
  874. },
  875. // startPollingOnlinePresence() {
  876. // // 每隔一定时间执行轮询任务
  877. // this.onlinePresenceInterval = setInterval(() => {
  878. // this.pollOnlinePresence();
  879. // }, 3000); // 3秒钟轮询一次,根据需要调整间隔时间
  880. // },
  881. // stopPollingOnlinePresence() {
  882. // // 清除定时器,停止轮询任务 !!!!重要,防止内存泄露
  883. // clearInterval(this.onlinePresenceInterval);
  884. // },
  885. // pollOnlinePresence() {
  886. // // 在这里执行轮询的任务,可以是发送请求或执行其他操作
  887. // listCameraOnlinePresence().then((response) => {
  888. // this.cameraList = response.data;
  889. // const children = response.data.map((item) => ({
  890. // ...item,
  891. // isLeaf: true,
  892. // label: item.cameraName,
  893. // key: item.id,
  894. // }));
  895. // this.onlinePresenceList = children;
  896. // });
  897. // },
  898. // 筛选节点
  899. filterNode(value, data) {
  900. if (!value) return true
  901. return data.label.indexOf(value) !== -1
  902. },
  903. setCurrentKeyTree(id) {
  904. if (this.activeName === 'first' || this.activeName === 'third') {
  905. this.$nextTick().then(() => {
  906. this.$refs.tree1.setCurrentKey(id)
  907. // console.log(this.$refs.tree1.getCurrentNode(id))
  908. this.equipmentInfo = this.$refs.tree1.getCurrentNode(id)
  909. const node = document.getElementById(id) // 通过Id获取到对应的dom元素
  910. setTimeout(() => {
  911. if (node) {
  912. this.$nextTick(() => {
  913. node.scrollIntoView({ block: 'center' }) // 通过scrollIntoView方法将对应的dom元素定位到可见区域 【block: 'center'】这个属性是在垂直方向居中显示
  914. })
  915. }
  916. }, 100)
  917. })
  918. } else if (this.activeName === 'second') {
  919. this.$nextTick().then(() => {
  920. this.$refs.tree2.setCurrentKey(id)
  921. this.equipmentInfo = this.$refs.tree2.getCurrentNode(id)
  922. var selected = this.$refs.tree2.getCurrentNode()
  923. if (
  924. this.$refs.tree2.getNode(selected) &&
  925. this.$refs.tree2.getNode(selected).parent
  926. ) {
  927. this.expandParents(this.$refs.tree2.getNode(selected).parent)
  928. }
  929. const node = document.getElementById('group' + id) // 通过Id获取到对应的dom元素
  930. setTimeout(() => {
  931. if (node) {
  932. this.$nextTick(() => {
  933. node.scrollIntoView({ block: 'center' }) // 通过scrollIntoView方法将对应的dom元素定位到可见区域 【block: 'center'】这个属性是在垂直方向居中显示
  934. })
  935. }
  936. }, 100)
  937. })
  938. }
  939. },
  940. expandParents(node) {
  941. node.expanded = true
  942. if (node.parent) {
  943. this.expandParents(node.parent)
  944. }
  945. },
  946. handleNodeClick(node) {
  947. this.fishEyeType = '鱼眼'
  948. this.activeTool = 'first'
  949. const debounceTimer = this.timer
  950. if (debounceTimer) {
  951. window.clearTimeout(debounceTimer)
  952. this.timer = null
  953. }
  954. this.timer = window.setTimeout(() => {
  955. console.log(node)
  956. // 判断是否是设备
  957. if (node.isLeaf) {
  958. this.equipmentInfo = node
  959. // 判断灯光状态
  960. if (this.equipmentInfo.isOutboard === '1') {
  961. // 判断灯光状态
  962. lamplightInfo({ id: this.equipmentInfo.lamplightEquipment }).then(
  963. (res) => {
  964. if (res.total === 0) {
  965. return
  966. } else {
  967. this.equipmentInfo.lamplightId = res.data.id
  968. this.equipmentInfo.lamplightOnline = res.data.lamplightOnline
  969. this.equipmentInfo.lamplightStatus = res.data.lamplightStatus
  970. this.newEquipmentInfo.lightSwitch = res.data.lightSwitch
  971. this.equipmentInfo.light = Number(res.data.light) * 20
  972. this.newEquipmentInfo.overallSwitch = res.data.overallSwitch
  973. this.newEquipmentInfo.moduleSwitch = res.data.moduleSwitch
  974. this.equipmentInfo.isGeneralControl = res.data.isGeneralControl
  975. }
  976. }
  977. )
  978. }
  979. this.$nextTick(() => {
  980. // 设置当前选中设备
  981. this.$store.commit('updateSelectedTreeData', node)
  982. this.$store.commit('updateSelectedMonitor', {})
  983. let isplaying = false
  984. this.boxList.forEach((item) => {
  985. if (item.cameraId === node.id) {
  986. this.$store.commit('updateSelectedMonitor', item)
  987. isplaying = true
  988. }
  989. })
  990. })
  991. } else {
  992. //点击了父节点
  993. this.$nextTick(() => {
  994. })
  995. }
  996. }, 300)
  997. },
  998. // 节点双击事件
  999. handleNodedbClick(node) {
  1000. console.log('dbclick')
  1001. this.fishEyeType = '鱼眼'
  1002. const debounceTimer = this.timer
  1003. if (debounceTimer) {
  1004. window.clearTimeout(debounceTimer)
  1005. this.timer = null
  1006. }
  1007. // 判断是否是设备
  1008. if (node.isLeaf) {
  1009. this.equipmentInfo = node
  1010. this.$nextTick(() => {
  1011. // 设置当前选中设备
  1012. this.$store.commit('updateSelectedTreeData', node)
  1013. this.$refs.video.setShowBorder(true)
  1014. // 遍历寻找空屏
  1015. let findBox = false
  1016. this.boxList.slice(0, this.active).forEach((item) => {
  1017. if (!findBox && !item.cameraId) {
  1018. findBox = true
  1019. this.$store.commit('updateSelectedMonitor', item)
  1020. }
  1021. })
  1022. // 遍历完了还没找到
  1023. if (!findBox) {
  1024. this.$store.commit(
  1025. 'updateSelectedMonitor',
  1026. this.boxList[this.active - 1]
  1027. )
  1028. }
  1029. // 判断设备是否停用
  1030. if (
  1031. this.onlinePresenceList.find(
  1032. (item) => item.id === this.selectedTreeData.id
  1033. ).onlinePresence === '1'
  1034. ) {
  1035. // 获取流
  1036. this.getPlayUrl(this.selectedMonitor)
  1037. } else {
  1038. this.$message.warning('当前设备已离线!')
  1039. this.clearTreeSelected()
  1040. }
  1041. })
  1042. if (this.equipmentInfo.isOutboard === '1') {
  1043. // 判断灯光状态
  1044. lamplightInfo({ id: this.equipmentInfo.lamplightEquipment }).then(
  1045. (res) => {
  1046. if (res.total === 0) {
  1047. return
  1048. } else {
  1049. this.equipmentInfo.lamplightId = res.data.id
  1050. this.equipmentInfo.lamplightOnline = res.data.lamplightOnline
  1051. this.equipmentInfo.lamplightStatus = res.data.lamplightStatus
  1052. this.newEquipmentInfo.lightSwitch = res.data.lightSwitch
  1053. this.equipmentInfo.light = Number(res.data.light) * 20
  1054. this.newEquipmentInfo.overallSwitch = res.data.overallSwitch
  1055. this.newEquipmentInfo.moduleSwitch = res.data.moduleSwitch
  1056. this.equipmentInfo.isGeneralControl = res.data.isGeneralControl
  1057. }
  1058. }
  1059. )
  1060. }
  1061. } else {
  1062. //双击了父节点
  1063. this.$nextTick(() => {
  1064. // 设置当前选中设备
  1065. this.boxList.forEach((item, index) => {
  1066. setTimeout(() => {
  1067. if (node.children[index]) {
  1068. this.$store.commit('updateSelectedMonitor', item)
  1069. this.$store.commit(
  1070. 'updateSelectedTreeData',
  1071. node.children[index]
  1072. )
  1073. // 判断设备是否停用
  1074. if (
  1075. this.onlinePresenceList.find(
  1076. (item) => item.id === this.selectedTreeData.id
  1077. ).onlinePresence === '1'
  1078. ) {
  1079. // 获取流
  1080. this.getPlayUrl(this.selectedMonitor)
  1081. } else {
  1082. // this.$message.warning('当前设备已离线!')
  1083. this.clearTreeSelected()
  1084. }
  1085. }
  1086. }, index * 600)
  1087. })
  1088. })
  1089. }
  1090. },
  1091. handleViewNodeClick(node) {
  1092. this.equipmentInfo = {}
  1093. this.viewId = node.id
  1094. },
  1095. handleViewNodedbClick(node) {
  1096. console.log(node)
  1097. this.equipmentInfo = {}
  1098. this.viewId = node.id
  1099. let data = JSON.parse(node.viewPreviewJson)
  1100. this.$store.commit('updateActive', data.active)
  1101. this.$store.commit('updateBoxList', data.boxList)
  1102. },
  1103. updateView() {
  1104. updatePreview({ id: this.viewId, viewName: this.viewName }).then(
  1105. (res) => {
  1106. this.viewName = ''
  1107. this.getViewOptions()
  1108. this.openUpdateView = false
  1109. this.$message.success('修改成功!')
  1110. }
  1111. )
  1112. },
  1113. deleteView(data) {
  1114. this.$modal
  1115. .confirm('是否确认删除名称为"' + data.label + '"的视图?')
  1116. .then(function() {
  1117. return deletePreview(data.id)
  1118. })
  1119. .then(() => {
  1120. this.getViewOptions()
  1121. this.$modal.msgSuccess('删除成功!')
  1122. })
  1123. .catch(() => {
  1124. })
  1125. },
  1126. getPlayUrl(item) {
  1127. // 清空流地址
  1128. this.$store.commit('updateSelectedMonitor', {
  1129. ...item,
  1130. mainUrl: '',
  1131. auxiliaryUrl: ''
  1132. })
  1133. // 获取流
  1134. const isFishEye = this.selectedTreeData.isFishEye === '1'
  1135. // const bitstreamType = this.active === 1 ? "0" : "1";
  1136. const appCondition = isFishEye ? '鱼眼' : ''
  1137. // 找所有符合条件的流
  1138. let info = this.equipmentInfo.streamProxyList.filter((item) =>
  1139. item.app.includes(appCondition)
  1140. )
  1141. console.log(info)
  1142. // 找不到的后续操作
  1143. if (info.length === 0) {
  1144. item.cameraId = this.selectedTreeData.id
  1145. item.name = this.selectedTreeData.cameraName
  1146. let object = JSON.parse(
  1147. this.equipmentInfo.streamProxyList[0].urlObject
  1148. )
  1149. item.code = object.codec_id_name
  1150. item.rtc = object.rtc
  1151. item.rtsp = object.rtsp
  1152. const isH264 = object.codec_id_name === 'H264'
  1153. const isH265 = object.codec_id_name === 'H265'
  1154. // item.mainUrl =
  1155. // location.protocol === "https:"
  1156. // ? isH264 || isH265
  1157. // ? isH264
  1158. // ? object.rtcs
  1159. // : object.https_flv
  1160. // : object.rtcs
  1161. // : isH264 || isH265
  1162. // ? isH264
  1163. // ? object.rtc
  1164. // : object.flv
  1165. // : object.rtc;
  1166. // item.auxiliaryUrl = item.mainUrl;
  1167. info = this.equipmentInfo.streamProxyList
  1168. if (info[0].typeOfBitstream === '0') {
  1169. item.mainUrl =
  1170. location.protocol === 'https:'
  1171. ? isH264 || isH265
  1172. ? isH264
  1173. ? object.rtcs
  1174. : object.https_flv
  1175. : object.rtcs
  1176. : isH264 || isH265
  1177. ? isH264
  1178. ? object.rtc
  1179. : object.flv
  1180. : object.rtc
  1181. if (info.length > 1) {
  1182. let object1 = JSON.parse(info[1].urlObject)
  1183. item.auxiliaryUrl =
  1184. location.protocol === 'https:'
  1185. ? isH264 || isH265
  1186. ? isH264
  1187. ? object1.rtcs
  1188. : object1.https_flv
  1189. : object1.rtcs
  1190. : isH264 || isH265
  1191. ? isH264
  1192. ? object1.rtc
  1193. : object1.flv
  1194. : object1.rtc
  1195. } else {
  1196. item.auxiliaryUrl = item.mainUrl
  1197. }
  1198. } else {
  1199. item.auxiliaryUrl =
  1200. location.protocol === 'https:'
  1201. ? isH264 || isH265
  1202. ? isH264
  1203. ? object.rtcs
  1204. : object.https_flv
  1205. : object.rtcs
  1206. : isH264 || isH265
  1207. ? isH264
  1208. ? object.rtc
  1209. : object.flv
  1210. : object.rtc
  1211. if (info.length > 1) {
  1212. let object1 = JSON.parse(info[1].urlObject)
  1213. item.mainUrl =
  1214. location.protocol === 'https:'
  1215. ? isH264 || isH265
  1216. ? isH264
  1217. ? object1.rtcs
  1218. : object1.https_flv
  1219. : object1.rtcs
  1220. : isH264 || isH265
  1221. ? isH264
  1222. ? object1.rtc
  1223. : object1.flv
  1224. : object1.rtc
  1225. } else {
  1226. item.mainUrl = item.auxiliaryUrl
  1227. }
  1228. }
  1229. } else {
  1230. item.cameraId = this.selectedTreeData.id
  1231. item.name = this.selectedTreeData.cameraName
  1232. let object = JSON.parse(info[0].urlObject)
  1233. item.code = object.codec_id_name
  1234. item.rtc = object.rtc
  1235. item.rtsp = object.rtsp
  1236. const isH264 = object.codec_id_name === 'H264'
  1237. const isH265 = object.codec_id_name === 'H265'
  1238. if (info[0].typeOfBitstream === '0') {
  1239. item.mainUrl =
  1240. location.protocol === 'https:'
  1241. ? isH264 || isH265
  1242. ? isH264
  1243. ? object.rtcs
  1244. : object.https_flv
  1245. : object.rtcs
  1246. : isH264 || isH265
  1247. ? isH264
  1248. ? object.rtc
  1249. : object.flv
  1250. : object.rtc
  1251. if (info.length > 1) {
  1252. let object1 = JSON.parse(info[1].urlObject)
  1253. item.auxiliaryUrl =
  1254. location.protocol === 'https:'
  1255. ? isH264 || isH265
  1256. ? isH264
  1257. ? object1.rtcs
  1258. : object1.https_flv
  1259. : object1.rtcs
  1260. : isH264 || isH265
  1261. ? isH264
  1262. ? object1.rtc
  1263. : object1.flv
  1264. : object1.rtc
  1265. } else {
  1266. item.auxiliaryUrl = item.mainUrl
  1267. }
  1268. } else {
  1269. item.auxiliaryUrl =
  1270. location.protocol === 'https:'
  1271. ? isH264 || isH265
  1272. ? isH264
  1273. ? object.rtcs
  1274. : object.https_flv
  1275. : object.rtcs
  1276. : isH264 || isH265
  1277. ? isH264
  1278. ? object.rtc
  1279. : object.flv
  1280. : object.rtc
  1281. if (info.length > 1) {
  1282. let object1 = JSON.parse(info[1].urlObject)
  1283. item.mainUrl =
  1284. location.protocol === 'https:'
  1285. ? isH264 || isH265
  1286. ? isH264
  1287. ? object1.rtcs
  1288. : object1.https_flv
  1289. : object1.rtcs
  1290. : isH264 || isH265
  1291. ? isH264
  1292. ? object1.rtc
  1293. : object1.flv
  1294. : object1.rtc
  1295. } else {
  1296. item.mainUrl = item.auxiliaryUrl
  1297. }
  1298. }
  1299. }
  1300. console.log('item', item)
  1301. },
  1302. clearTreeSelected() {
  1303. this.$store.commit('updateSelectedTreeData', {})
  1304. this.$store.commit('updateSelectedMonitor', {})
  1305. // this.selectedTree = []
  1306. },
  1307. clickToolBar(value) {
  1308. if (value === 1) {
  1309. this.$refs.toolbar.one()
  1310. }
  1311. },
  1312. // 开始轮询
  1313. startPolling(duration, interval) {
  1314. // 时间到了停止轮询
  1315. setTimeout(() => {
  1316. this.endPolling()
  1317. }, duration * 1000 * 60)
  1318. // 清空boxList 只留boxId
  1319. this.$store.commit(
  1320. 'updateBoxList',
  1321. this.boxList.map((item) => ({ boxId: item.boxId }))
  1322. )
  1323. let viewCount = this.active
  1324. console.log('viewCount', viewCount)
  1325. // 页面足够不需要切换页面
  1326. if (this.cameraList.length <= viewCount) {
  1327. this.$nextTick(() => {
  1328. // 设置当前选中设备
  1329. this.boxList.forEach((item, index) => {
  1330. setTimeout(() => {
  1331. if (this.cameraList[index]) {
  1332. this.equipmentInfo = this.cameraList[index]
  1333. this.$store.commit('updateSelectedMonitor', item)
  1334. this.$store.commit(
  1335. 'updateSelectedTreeData',
  1336. this.cameraList[index]
  1337. )
  1338. this.$refs.video.setShowBorder(true)
  1339. // 判断设备是否停用
  1340. if (
  1341. this.onlinePresenceList.find(
  1342. (item) => item.id === this.selectedTreeData.id
  1343. ).onlinePresence === '1'
  1344. ) {
  1345. // 获取流
  1346. this.getPlayUrl(this.selectedMonitor)
  1347. } else {
  1348. this.$message.warning(
  1349. this.selectedTreeData.cameraName + '设备已离线!'
  1350. )
  1351. this.clearTreeSelected()
  1352. }
  1353. }
  1354. }, index * 600)
  1355. })
  1356. })
  1357. } else {
  1358. let cameraIndex = 0
  1359. this.pollingInterval = setInterval(() => {
  1360. if (cameraIndex >= this.cameraList.length) {
  1361. cameraIndex = 0
  1362. }
  1363. this.$nextTick(() => {
  1364. // 设置当前选中设备
  1365. this.boxList.slice(0, viewCount).forEach((item, index) => {
  1366. setTimeout(() => {
  1367. if (cameraIndex < this.cameraList.length) {
  1368. this.equipmentInfo = this.cameraList[cameraIndex]
  1369. this.$store.commit('updateSelectedMonitor', item)
  1370. this.$store.commit(
  1371. 'updateSelectedTreeData',
  1372. this.cameraList[cameraIndex]
  1373. )
  1374. this.$refs.video.setShowBorder(true)
  1375. cameraIndex++
  1376. // 判断设备是否停用
  1377. if (
  1378. this.onlinePresenceList.find(
  1379. (item) => item.id === this.selectedTreeData.id
  1380. ).onlinePresence === '1'
  1381. ) {
  1382. // 获取流
  1383. this.getPlayUrl(this.selectedMonitor)
  1384. } else {
  1385. this.$message.warning(
  1386. this.selectedTreeData.cameraName + '设备已离线!'
  1387. )
  1388. this.clearTreeSelected()
  1389. }
  1390. }
  1391. }, index * 600)
  1392. })
  1393. })
  1394. }, interval * 1000)
  1395. }
  1396. },
  1397. endPolling() {
  1398. clearInterval(this.pollingInterval)
  1399. this.pollingInterval = null
  1400. this.$refs.toolbar.changePollingStatus()
  1401. },
  1402. save() {
  1403. savePreview({
  1404. viewName: this.viewName,
  1405. viewPreviewJson: {
  1406. active: this.$store.getters.active,
  1407. boxList: this.$store.getters.boxList
  1408. },
  1409. userId: this.$store.getters.userId
  1410. }).then((res) => {
  1411. this.viewName = ''
  1412. this.getViewOptions()
  1413. this.openSave = false
  1414. this.$message.success('保存成功!')
  1415. })
  1416. },
  1417. beforeShare() {
  1418. this.openShare = true
  1419. this.loading = true
  1420. listUser().then((response) => {
  1421. this.userList = response.rows
  1422. // this.total = response.total;
  1423. this.loading = false
  1424. })
  1425. },
  1426. // 多选框选中数据
  1427. handleSelectionChange(selection) {
  1428. this.ids = selection.map((item) => item.userId)
  1429. this.single = selection.length != 1
  1430. this.multiple = !selection.length
  1431. },
  1432. share() {
  1433. sharePreview({ userId: this.ids, viewId: this.viewId }).then((res) => {
  1434. this.ids = []
  1435. this.openShare = false
  1436. this.$message.success('分享成功!')
  1437. })
  1438. },
  1439. // seize() {
  1440. // seize({ userId: this.$store.getters.userId, equId: this.equipmentInfo.id, seizeTime: this.seizeTime }).then(res => {
  1441. // this.$message.success('抢占成功!')
  1442. // })
  1443. // },
  1444. fisheye() {
  1445. this.boxList.forEach((item) => {
  1446. if (item.cameraId === this.equipmentInfo.id) {
  1447. this.$store.commit('updateSelectedMonitor', item)
  1448. if (this.fishEyeType === '鱼眼') {
  1449. this.$nextTick(() => {
  1450. // // 获取流
  1451. // fishEyeChange({ id: this.equipmentInfo.id, mode: "全景" }).then(
  1452. // (res) => {
  1453. // if (res.data !== "" && res.data.success) {
  1454. // if (
  1455. // res.data.data.tracks[0].codec_id_name === "H264" ||
  1456. // res.data.data.tracks[0].codec_id_name !== "H265"
  1457. // ) {
  1458. // item.url =
  1459. // location.protocol === "https:"
  1460. // ? res.data.data.rtcs
  1461. // : res.data.data.rtc;
  1462. // } else {
  1463. // item.url =
  1464. // location.protocol === "https:"
  1465. // ? res.data.data.https_flv
  1466. // : res.data.data.flv;
  1467. // }
  1468. // this.$message.success("切换成功!");
  1469. // console.log(this.boxList);
  1470. // } else {
  1471. // this.$message.warning(
  1472. // this.selectedTreeData.cameraName + "获取播放链接失败!"
  1473. // );
  1474. // }
  1475. // }
  1476. // );
  1477. // 找所有符合条件的流
  1478. let info = this.equipmentInfo.streamProxyList.filter((item) =>
  1479. item.app.includes('全景')
  1480. )
  1481. // 找不到的后续操作
  1482. if (info.length === 0) {
  1483. let object = JSON.parse(
  1484. this.equipmentInfo.streamProxyList[0].urlObject
  1485. )
  1486. const isH264 = object.codec_id_name === 'H264'
  1487. const isH265 = object.codec_id_name === 'H265'
  1488. item.mainUrl =
  1489. location.protocol === 'https:'
  1490. ? isH264 || isH265
  1491. ? isH264
  1492. ? object.rtcs
  1493. : object.https_flv
  1494. : object.rtcs
  1495. : isH264 || isH265
  1496. ? isH264
  1497. ? object.rtc
  1498. : object.flv
  1499. : object.rtc
  1500. item.auxiliaryUrl = item.mainUrl
  1501. } else {
  1502. let object = JSON.parse(info[0].urlObject)
  1503. const isH264 = object.codec_id_name === 'H264'
  1504. const isH265 = object.codec_id_name === 'H265'
  1505. if (info[0].typeOfBitstream === '0') {
  1506. item.mainUrl =
  1507. location.protocol === 'https:'
  1508. ? isH264 || isH265
  1509. ? isH264
  1510. ? object.rtcs
  1511. : object.https_flv
  1512. : object.rtcs
  1513. : isH264 || isH265
  1514. ? isH264
  1515. ? object.rtc
  1516. : object.flv
  1517. : object.rtc
  1518. if (info.length > 1) {
  1519. let object1 = JSON.parse(info[1].urlObject)
  1520. item.auxiliaryUrl =
  1521. location.protocol === 'https:'
  1522. ? isH264 || isH265
  1523. ? isH264
  1524. ? object1.rtcs
  1525. : object1.https_flv
  1526. : object1.rtcs
  1527. : isH264 || isH265
  1528. ? isH264
  1529. ? object1.rtc
  1530. : object1.flv
  1531. : object1.rtc
  1532. } else {
  1533. item.auxiliaryUrl = item.mainUrl
  1534. }
  1535. } else {
  1536. item.auxiliaryUrl =
  1537. location.protocol === 'https:'
  1538. ? isH264 || isH265
  1539. ? isH264
  1540. ? object1.rtcs
  1541. : object1.https_flv
  1542. : object1.rtcs
  1543. : isH264 || isH265
  1544. ? isH264
  1545. ? object1.rtc
  1546. : object1.flv
  1547. : object1.rtc
  1548. if (info.length > 1) {
  1549. let object1 = JSON.parse(info[1].urlObject)
  1550. item.mainUrl =
  1551. location.protocol === 'https:'
  1552. ? isH264 || isH265
  1553. ? isH264
  1554. ? object1.rtcs
  1555. : object1.https_flv
  1556. : object1.rtcs
  1557. : isH264 || isH265
  1558. ? isH264
  1559. ? object1.rtc
  1560. : object1.flv
  1561. : object1.rtc
  1562. } else {
  1563. item.mainUrl = item.auxiliaryUrl
  1564. }
  1565. }
  1566. }
  1567. this.$message.success('切换成功')
  1568. this.fishEyeType = '全景'
  1569. })
  1570. } else {
  1571. this.$nextTick(() => {
  1572. // // 获取流
  1573. // fishEyeChange({ id: this.equipmentInfo.id, mode: "鱼眼" }).then(
  1574. // (res) => {
  1575. // if (res.data !== "" && res.data.success) {
  1576. // if (
  1577. // res.data.data.tracks[0].codec_id_name === "H264" ||
  1578. // res.data.data.tracks[0].codec_id_name !== "H265"
  1579. // ) {
  1580. // item.url =
  1581. // location.protocol === "https:"
  1582. // ? res.data.data.rtcs
  1583. // : res.data.data.rtc;
  1584. // } else {
  1585. // item.url =
  1586. // location.protocol === "https:"
  1587. // ? res.data.data.https_flv
  1588. // : res.data.data.flv;
  1589. // }
  1590. // this.$message.success("切换成功!");
  1591. // console.log(this.boxList);
  1592. // } else {
  1593. // this.$message.warning(
  1594. // this.selectedTreeData.cameraName + "获取播放链接失败!"
  1595. // );
  1596. // }
  1597. // }
  1598. // );
  1599. // 找所有符合条件的流
  1600. let info = this.equipmentInfo.streamProxyList.filter((item) =>
  1601. item.app.includes('鱼眼')
  1602. )
  1603. // 找不到的后续操作
  1604. if (info.length === 0) {
  1605. let object = JSON.parse(
  1606. this.equipmentInfo.streamProxyList[0].urlObject
  1607. )
  1608. const isH264 = object.codec_id_name === 'H264'
  1609. const isH265 = object.codec_id_name === 'H265'
  1610. item.mainUrl =
  1611. location.protocol === 'https:'
  1612. ? isH264 || isH265
  1613. ? isH264
  1614. ? object.rtcs
  1615. : object.https_flv
  1616. : object.rtcs
  1617. : isH264 || isH265
  1618. ? isH264
  1619. ? object.rtc
  1620. : object.flv
  1621. : object.rtc
  1622. item.auxiliaryUrl = item.mainUrl
  1623. } else {
  1624. let object = JSON.parse(info[0].urlObject)
  1625. const isH264 = object.codec_id_name === 'H264'
  1626. const isH265 = object.codec_id_name === 'H265'
  1627. if (info[0].typeOfBitstream === '0') {
  1628. item.mainUrl =
  1629. location.protocol === 'https:'
  1630. ? isH264 || isH265
  1631. ? isH264
  1632. ? object.rtcs
  1633. : object.https_flv
  1634. : object.rtcs
  1635. : isH264 || isH265
  1636. ? isH264
  1637. ? object.rtc
  1638. : object.flv
  1639. : object.rtc
  1640. if (info.length > 1) {
  1641. let object1 = JSON.parse(info[1].urlObject)
  1642. item.auxiliaryUrl =
  1643. location.protocol === 'https:'
  1644. ? isH264 || isH265
  1645. ? isH264
  1646. ? object1.rtcs
  1647. : object1.https_flv
  1648. : object1.rtcs
  1649. : isH264 || isH265
  1650. ? isH264
  1651. ? object1.rtc
  1652. : object1.flv
  1653. : object1.rtc
  1654. } else {
  1655. item.auxiliaryUrl = item.mainUrl
  1656. }
  1657. } else {
  1658. item.auxiliaryUrl =
  1659. location.protocol === 'https:'
  1660. ? isH264 || isH265
  1661. ? isH264
  1662. ? object1.rtcs
  1663. : object1.https_flv
  1664. : object1.rtcs
  1665. : isH264 || isH265
  1666. ? isH264
  1667. ? object1.rtc
  1668. : object1.flv
  1669. : object1.rtc
  1670. if (info.length > 1) {
  1671. let object1 = JSON.parse(info[1].urlObject)
  1672. item.mainUrl =
  1673. location.protocol === 'https:'
  1674. ? isH264 || isH265
  1675. ? isH264
  1676. ? object1.rtcs
  1677. : object1.https_flv
  1678. : object1.rtcs
  1679. : isH264 || isH265
  1680. ? isH264
  1681. ? object1.rtc
  1682. : object1.flv
  1683. : object1.rtc
  1684. } else {
  1685. item.mainUrl = item.auxiliaryUrl
  1686. }
  1687. }
  1688. }
  1689. this.$message.success('切换成功')
  1690. this.fishEyeType = '鱼眼'
  1691. })
  1692. }
  1693. }
  1694. })
  1695. },
  1696. // 灯光开关
  1697. handleOpenLight() {
  1698. let text = this.equipmentInfo.lamplightStatus === '1' ? '启用' : '停用'
  1699. this.$modal
  1700. .confirm('确认要"' + text + '"吗?')
  1701. .then(() => {
  1702. if (text === '启用') {
  1703. return power({
  1704. deviceId: this.equipmentInfo.lamplightId,
  1705. powerOn: true
  1706. })
  1707. } else {
  1708. return power({
  1709. deviceId: this.equipmentInfo.lamplightId,
  1710. powerOn: false
  1711. })
  1712. }
  1713. })
  1714. .then(() => {
  1715. this.$modal.msgSuccess(text + '成功')
  1716. lamplightInfo({ id: this.equipmentInfo.lamplightEquipment }).then(
  1717. (res) => {
  1718. if (res.total === 0) {
  1719. return
  1720. } else {
  1721. this.equipmentInfo.lamplightId = res.data.id
  1722. this.equipmentInfo.lamplightOnline = res.data.lamplightOnline
  1723. this.equipmentInfo.lamplightStatus = this.equipmentInfo.lamplightStatus === '1' ? '1' : '0'
  1724. this.newEquipmentInfo.lightSwitch = !this.newEquipmentInfo.lightSwitch
  1725. this.equipmentInfo.light = Number(res.data.light) * 20
  1726. this.newEquipmentInfo.overallSwitch = res.data.overallSwitch
  1727. this.newEquipmentInfo.moduleSwitch = res.data.moduleSwitch
  1728. this.equipmentInfo.isGeneralControl = res.data.isGeneralControl
  1729. console.log(this.newEquipmentInfo.lightSwitch)
  1730. console.log(this.equipmentInfo.lamplightStatus)
  1731. }
  1732. }
  1733. )
  1734. })
  1735. .catch(() => {
  1736. this.equipmentInfo.lamplightStatus =
  1737. this.equipmentInfo.lamplightStatus === '0' ? '1' : '0'
  1738. })
  1739. },
  1740. changeLight() {
  1741. if (this.equipmentInfo.lamplightStatus != '1') {
  1742. this.$modal.msgError('请先开启灯光')
  1743. return
  1744. }
  1745. this.fullscreenLoading = true
  1746. dim({
  1747. deviceId: this.equipmentInfo.lamplightId,
  1748. dimLevel: this.equipmentInfo.light / 20
  1749. }).then(() => {
  1750. this.fullscreenLoading = false
  1751. this.$modal.msgSuccess('调光成功')
  1752. }).catch(() => {
  1753. this.fullscreenLoading = false
  1754. })
  1755. },
  1756. handleMove(val) {
  1757. switch (val) {
  1758. case 'up':
  1759. this.upIcon=upImg1
  1760. shotUp({ id: this.equipmentInfo.id, speed: this.speed }).then(
  1761. (res) => {
  1762. }
  1763. )
  1764. break
  1765. case 'upEnter':
  1766. this.upIcon=upImg1
  1767. break
  1768. case 'left':
  1769. this.leftIcon=leftImg1
  1770. shotLeft({ id: this.equipmentInfo.id, speed: this.speed }).then(
  1771. (res) => {
  1772. }
  1773. )
  1774. break
  1775. case 'leftEnter':
  1776. this.leftIcon=leftImg1
  1777. break
  1778. case 'right':
  1779. this.rightIcon=rightImg1
  1780. shotRight({ id: this.equipmentInfo.id, speed: this.speed }).then(
  1781. (res) => {
  1782. }
  1783. )
  1784. break
  1785. case 'rightEnter':
  1786. this.rightIcon=rightImg1
  1787. break
  1788. case 'down':
  1789. this.downIcon=downImg1
  1790. shotDown({ id: this.equipmentInfo.id, speed: this.speed }).then(
  1791. (res) => {
  1792. }
  1793. )
  1794. break
  1795. case 'downEnter':
  1796. this.downIcon=downImg1
  1797. break
  1798. case 'leftUp':
  1799. this.leftUpIcon=leftUpImg1
  1800. leftUp({ id: this.equipmentInfo.id, speed: this.speed }).then(
  1801. (res) => {
  1802. }
  1803. )
  1804. break
  1805. case 'leftUpEnter':
  1806. this.leftUpIcon=leftUpImg1
  1807. break
  1808. case 'rightUp':
  1809. this.rightUpIcon=rightUpImg1
  1810. rightUp({ id: this.equipmentInfo.id, speed: this.speed }).then(
  1811. (res) => {
  1812. }
  1813. )
  1814. break
  1815. case 'rightUpEnter':
  1816. this.rightUpIcon=rightUpImg1
  1817. break
  1818. case 'leftDown':
  1819. this.leftDownIcon=leftDownImg1
  1820. leftDown({ id: this.equipmentInfo.id, speed: this.speed }).then(
  1821. (res) => {
  1822. }
  1823. )
  1824. break
  1825. case 'leftDownEnter':
  1826. this.leftDownIcon=leftDownImg1
  1827. break
  1828. case 'rightDown':
  1829. this.rightDownIcon=rightDownImg1
  1830. rightDown({ id: this.equipmentInfo.id, speed: this.speed }).then(
  1831. (res) => {
  1832. }
  1833. )
  1834. break
  1835. case 'rightDownEnter':
  1836. this.rightDownIcon=rightDownImg1
  1837. break
  1838. case 'stop':
  1839. this.upIcon=upImg
  1840. this.leftUpIcon=leftUpImg
  1841. this.rightUpIcon=rightUpImg
  1842. this.leftIcon=leftImg
  1843. this.rightIcon=rightImg
  1844. this.leftDownIcon=leftDownImg
  1845. this.downIcon=downImg
  1846. this.rightDownIcon=rightDownImg
  1847. stopMove({ id: this.equipmentInfo.id, speed: this.speed }).then(
  1848. (res) => {
  1849. }
  1850. )
  1851. break
  1852. case 'leave':
  1853. this.upIcon=upImg
  1854. this.leftUpIcon=leftUpImg
  1855. this.rightUpIcon=rightUpImg
  1856. this.leftIcon=leftImg
  1857. this.rightIcon=rightImg
  1858. this.leftDownIcon=leftDownImg
  1859. this.downIcon=downImg
  1860. this.rightDownIcon=rightDownImg
  1861. break
  1862. }
  1863. },
  1864. addSpeed() {
  1865. const speed = (this.speed * 10 + 1) / 10
  1866. if (speed > 1) {
  1867. this.speed = 1
  1868. } else {
  1869. this.speed = speed
  1870. }
  1871. },
  1872. delSpeed() {
  1873. const speed = (this.speed * 10 - 1) / 10
  1874. if (speed < 0.1) {
  1875. this.speed = 0.1
  1876. } else {
  1877. this.speed = speed
  1878. }
  1879. },
  1880. handleFocusing(val) {
  1881. switch (val) {
  1882. case 'up':
  1883. this.double=doubleImg1
  1884. upFocalLength({ id: this.equipmentInfo.id, speed: this.speed }).then(
  1885. (res) => {
  1886. }
  1887. )
  1888. break
  1889. case 'upEnter':
  1890. this.double=doubleImg1
  1891. break
  1892. case 'down':
  1893. this.subtract=subtractImg1
  1894. downFocalLength({
  1895. id: this.equipmentInfo.id,
  1896. speed: this.speed
  1897. }).then((res) => {
  1898. })
  1899. break
  1900. case 'downEnter':
  1901. this.subtract=subtractImg1
  1902. break
  1903. case 'stop':
  1904. this.double=doubleImg
  1905. this.subtract=subtractImg
  1906. this.double1=doubleImg
  1907. this.subtract1=subtractImg
  1908. stopMove({ id: this.equipmentInfo.id }).then((res) => {
  1909. })
  1910. break
  1911. case 'focusIn':
  1912. this.subtract1=subtractImg1
  1913. focusIn({ id: this.equipmentInfo.id, speed: this.speed }).then((res) => {
  1914. })
  1915. break
  1916. case 'focusInEnter':
  1917. this.subtract1=subtractImg1
  1918. break
  1919. case 'focusOut':
  1920. this.double1=doubleImg1
  1921. focusOut({ id: this.equipmentInfo.id, speed: this.speed }).then((res) => {
  1922. })
  1923. break
  1924. case 'focusOutEnter':
  1925. this.double1=doubleImg1
  1926. break
  1927. case 'leave':
  1928. this.double=doubleImg
  1929. this.subtract=subtractImg
  1930. this.double1=doubleImg
  1931. this.subtract1=subtractImg
  1932. break
  1933. }
  1934. },
  1935. initSSE() {
  1936. const url = `${configPage.httpServe}/sse/stream`
  1937. this.eventSource = new EventSource(url)
  1938. this.eventSource.onmessage = (event) => {
  1939. const data = JSON.parse(event.data)
  1940. if (Array.isArray(data)) {
  1941. console.log('jsonData is an array.')
  1942. console.log(data)
  1943. this.cameraList = data
  1944. const children = data.map((item) => ({
  1945. ...item,
  1946. isLeaf: true,
  1947. label: item.cameraName,
  1948. key: item.id
  1949. }))
  1950. // 遍历onlinePresenceList
  1951. console.log(this.onlinePresenceList)
  1952. this.$nextTick(() => {
  1953. this.onlinePresenceList.forEach((item) => {
  1954. if (item.onlinePresence === '0') {
  1955. let node = children.find((child) => child.id === item.id)
  1956. if (node.onlinePresence === '1') {
  1957. // 遍历boxList
  1958. this.boxList.forEach((box) => {
  1959. if (box.cameraId === item.id) {
  1960. this.$store.commit('updateSelectedMonitor', box)
  1961. this.$refs.video.setShowBorder(true)
  1962. let boxTemp = JSON.parse(JSON.stringify(box))
  1963. this.$refs.video.close(box.boxId)
  1964. console.log(this.boxList)
  1965. setTimeout(() => {
  1966. this.boxList[box.boxId - 1] = boxTemp
  1967. console.log(this.boxList)
  1968. this.$store.commit('updateSelectedMonitor', box)
  1969. this.$refs.video.setShowBorder(true)
  1970. this.$store.commit('updateBoxList', this.boxList)
  1971. }, 1000)
  1972. }
  1973. })
  1974. }
  1975. }
  1976. })
  1977. this.onlinePresenceList = children
  1978. })
  1979. } else if (typeof data === 'object' && data !== null) {
  1980. console.log(this.userId === Number(data.userId))
  1981. if (this.userId === Number(data.userId)) {
  1982. this.$message({
  1983. type: 'error',
  1984. message:
  1985. '名称为:' +
  1986. data.name +
  1987. '的云台已被' +
  1988. data.newUserId +
  1989. '抢占!'
  1990. })
  1991. }
  1992. } else {
  1993. console.log('jsonData is neither an array nor an object.')
  1994. }
  1995. }
  1996. // 监听错误事件
  1997. this.eventSource.onerror = (err) => {
  1998. console.error('SSE error:', err)
  1999. this.handleReconnect(err)
  2000. }
  2001. // 监听关闭事件
  2002. this.eventSource.onclose = () => {
  2003. console.error('SSE connection closed.')
  2004. this.handleReconnect()
  2005. }
  2006. },
  2007. closeSSE() {
  2008. if (this.eventSource) {
  2009. this.eventSource.close()
  2010. this.eventSource = null // Clear the reference to prevent accidental reuse
  2011. }
  2012. },
  2013. handleReconnect(error) {
  2014. // 清除旧的EventSource实例
  2015. if (this.eventSource) {
  2016. this.eventSource.close()
  2017. }
  2018. // 重连间隔时间(毫秒)
  2019. const reconnectInterval = 5000
  2020. // 重连逻辑
  2021. setTimeout(() => {
  2022. console.log('Attempting to reconnect...')
  2023. this.initSSE()
  2024. }, reconnectInterval)
  2025. },
  2026. },
  2027. beforeRouteLeave(to, from, next) {
  2028. // 检查是否在录像
  2029. if (this.boxList.some((item) => item.recording === true)) {
  2030. this.$message.warning('正在录像中,请先结束录像!')
  2031. // const answer = window.confirm('你确定要离开这个页面吗?你可能有未保存的更改。');
  2032. //取消导航
  2033. next(false)
  2034. } else {
  2035. // 如果没有,直接继续导航
  2036. // this.stopPollingOnlinePresence()
  2037. next()
  2038. }
  2039. }
  2040. }
  2041. </script>
  2042. <style lang="scss" scoped>
  2043. @import "~@/assets/styles/mixin.scss";
  2044. @import "~@/assets/styles/variables.scss";
  2045. .app-wrapper {
  2046. @include clearfix;
  2047. position: relative;
  2048. height: 100%;
  2049. width: 100%;
  2050. &.mobile.openSidebar {
  2051. position: fixed;
  2052. top: 0;
  2053. }
  2054. }
  2055. .drawer-bg {
  2056. background: #000;
  2057. opacity: 0.3;
  2058. width: 100%;
  2059. top: 0;
  2060. height: 100%;
  2061. position: absolute;
  2062. z-index: 999;
  2063. }
  2064. .fixed-header {
  2065. position: fixed;
  2066. top: 0;
  2067. right: 0;
  2068. z-index: 9;
  2069. width: calc(100% - #{$base-sidebar-width});
  2070. transition: width 0.28s;
  2071. }
  2072. .hideSidebar .fixed-header {
  2073. width: calc(100% - 54px);
  2074. }
  2075. .sidebarHide .fixed-header {
  2076. width: 100%;
  2077. }
  2078. .mobile .fixed-header {
  2079. width: 100%;
  2080. }
  2081. .app-container {
  2082. min-height: 100%;
  2083. padding: 5px 5px;
  2084. //background: #1a1a2e;
  2085. -webkit-user-select: none;
  2086. /*webkit浏览器*/
  2087. -moz-user-select: none;
  2088. /*火狐*/
  2089. -ms-user-select: none;
  2090. /*IE10*/
  2091. user-select: none;
  2092. }
  2093. ::v-deep .el-tree {
  2094. background-color: transparent;
  2095. }
  2096. ::v-deep .el-tree-node__content {
  2097. margin: 3px;
  2098. background-color: #030c18;
  2099. color: #ffffff;
  2100. height: 40px;
  2101. }
  2102. ::v-deep .el-tree-node__children{
  2103. margin: 3px;
  2104. }
  2105. ::v-deep .el-tree__empty-block {
  2106. background-color: #1a2c43;
  2107. color: #ffffff;
  2108. }
  2109. ::v-deep .el-tree-node.is-current > .el-tree-node__content {
  2110. background-image: linear-gradient(to right, #acb3bb, #304156 100%);
  2111. font-weight: bold;
  2112. }
  2113. ::v-deep .el-tree-node:focus > .el-tree-node__content {
  2114. background-color: transparent;
  2115. }
  2116. ::v-deep .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
  2117. background-color: transparent;
  2118. }
  2119. ::v-deep .el-carousel__container {
  2120. height: 100%;
  2121. }
  2122. ::v-deep .el-carousel__arrow {
  2123. display: none !important;
  2124. }
  2125. ::v-deep .el-carousel__indicator {
  2126. display: none !important;
  2127. }
  2128. ::v-deep .el-tabs {
  2129. flex: 1;
  2130. display: flex;
  2131. flex-direction: column;
  2132. background-color: #1a2c43;
  2133. }
  2134. ::v-deep .el-tabs__header {
  2135. margin: 0 0 0px;
  2136. //background-color: #032046;
  2137. }
  2138. .head-container{
  2139. margin-bottom: 5px;
  2140. .el-tabs{
  2141. background: none;
  2142. }
  2143. background-image: url("../assets/images/kuang-2.png") !important;
  2144. background-repeat: no-repeat !important;
  2145. background-size: 220px 100% !important;
  2146. }
  2147. ::v-deep .head-container .el-tabs__content {
  2148. height: 40.5vh;
  2149. flex-grow: 1;
  2150. //background-color: #030c18;
  2151. overflow-y: auto;
  2152. /* 滚动槽 */
  2153. &::-webkit-scrollbar-track {
  2154. background-color: transparent;
  2155. }
  2156. }
  2157. ::v-deep .tool-tab .el-tabs__content {
  2158. height: 30vh;
  2159. flex-grow: 1;
  2160. //background-color: #030c18;
  2161. overflow-y: auto;
  2162. /* 滚动槽 */
  2163. &::-webkit-scrollbar-track {
  2164. background-color: transparent;
  2165. }
  2166. }
  2167. ::v-deep .el-tabs__item {
  2168. padding: 0;
  2169. font-weight: bold;
  2170. font-size: 16px;
  2171. color: #ffffff;
  2172. }
  2173. ::v-deep .el-tabs__nav-wrap::after {
  2174. background-color: transparent;
  2175. }
  2176. ::v-deep .tool-tab {
  2177. .el-tabs{
  2178. background: none;
  2179. }
  2180. background-image: url("../assets/images/kuang-2.png") !important;
  2181. background-repeat: no-repeat !important;
  2182. background-size: 220px 100% !important;
  2183. flex: 1;
  2184. display: flex;
  2185. flex-direction: column;
  2186. //margin-top:20%;
  2187. ::v-deep .el-tabs__content {
  2188. flex: 1 !important;
  2189. }
  2190. }
  2191. ::v-deep .el-tab-pane{
  2192. margin: 3px;
  2193. }
  2194. ::v-deep .el-slider__button {
  2195. border: none;
  2196. }
  2197. .el-button {
  2198. background-color: #6e7a89 !important;
  2199. color: #ffffff;
  2200. }
  2201. .tree-card {
  2202. display: flex;
  2203. flex-direction: column;
  2204. border: none;
  2205. min-height: calc(100vh - 84px);
  2206. padding: 0px 0px;
  2207. background-color: transparent;
  2208. }
  2209. ::v-deep .el-input__inner {
  2210. border: none;
  2211. //background-color: #6e7a89;
  2212. background-color: #0d1a2b;
  2213. color: #ffffff;
  2214. }
  2215. ::v-deep .el-switch__label {
  2216. color: #ffffff;
  2217. }
  2218. .fast-button {
  2219. border-radius: 5px;
  2220. border: 2px solid #043f92;
  2221. display: flex;
  2222. align-items: center;
  2223. justify-content: center;
  2224. background-color: #032554;
  2225. color: #ffffff;
  2226. font-size: 14px;
  2227. height: 35px;
  2228. width: 45%;
  2229. min-width: 100px;
  2230. margin: 15px 0px 0px 0px;
  2231. }
  2232. .operate-panel {
  2233. display: flex;
  2234. flex-direction: column;
  2235. align-items: center;
  2236. justify-content: space-around;
  2237. margin: 0 auto;
  2238. padding: 10px;
  2239. background: transparent;
  2240. position: relative;
  2241. }
  2242. .move-btn {
  2243. background-size: 225px;
  2244. background-image: url("../assets/images/ptz-bg.png") ;
  2245. margin-top: 5px;
  2246. margin-bottom: 5px;
  2247. padding: 3px 5px 5px 3px;
  2248. width: 220px;
  2249. height: 210px;
  2250. //background-color: #6e7a89;
  2251. //color: #ffffff;
  2252. //border-radius: 65px;
  2253. //box-shadow: 0px 0px 2px 4px #a7a6a6;
  2254. display: flex;
  2255. flex-wrap: wrap;
  2256. align-items: center;
  2257. justify-content: center;
  2258. position: relative;
  2259. }
  2260. .btn {
  2261. //margin: 10px;
  2262. width: 30px;
  2263. height: 30px;
  2264. }
  2265. ::v-deep .el-icon-arrow-up {
  2266. font-weight: bold;
  2267. text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
  2268. }
  2269. .compose-btn {
  2270. margin-top: 10px;
  2271. width: 100%;
  2272. //display: flex;
  2273. //flex-direction: column;
  2274. //align-items: center;
  2275. //justify-content: space-around;
  2276. }
  2277. .btn2 {
  2278. height: 23px;
  2279. width: 90%;
  2280. margin-top: 8px;
  2281. padding: 6px 4px;
  2282. border-radius: 15px;
  2283. background: #6e7a89;
  2284. color: #ffffff;
  2285. font-size: 18px;
  2286. display: flex;
  2287. text-align: center;
  2288. justify-content: space-between;
  2289. align-items: center;
  2290. flex-direction: row;
  2291. }
  2292. ///* 滚动槽 */
  2293. //&::-webkit-scrollbar-track {
  2294. // background-color: transparent;
  2295. //}
  2296. .device-info {
  2297. margin-top: 20px;
  2298. }
  2299. .info-item {
  2300. display: flex;
  2301. flex-direction: column;
  2302. align-items: center;
  2303. margin-bottom: 10px;
  2304. width: 80px;
  2305. }
  2306. .status-light {
  2307. width: 20px;
  2308. height: 20px;
  2309. border-radius: 50%;
  2310. margin-bottom: 10px;
  2311. }
  2312. .status-light.active {
  2313. background-color: green;
  2314. }
  2315. .status-light.inactive {
  2316. background-color: grey;
  2317. }
  2318. .info-item span {
  2319. color: white;
  2320. }
  2321. .btn1{
  2322. width: 60px;
  2323. height: 35px;
  2324. }
  2325. .div-class{
  2326. width: 45px;
  2327. height: 45px;
  2328. float: left;
  2329. }
  2330. .span-class{
  2331. background-color: #031e43;
  2332. width: 40px;
  2333. height: 40px;
  2334. border: 1px solid black;
  2335. color: white;
  2336. display: flex;
  2337. align-items: center;
  2338. justify-content: center
  2339. }
  2340. .span-class1{
  2341. background-color: #031e43;
  2342. width: 40px;
  2343. height: 40px;
  2344. border: 1px solid black;
  2345. color: white;
  2346. display: flex;
  2347. align-items: center;
  2348. justify-content: center;
  2349. float: left;
  2350. }
  2351. ::v-deep .el-dialog .el-dialog__header{
  2352. background-color: #032046 !important;
  2353. }
  2354. ::v-deep .el-dialog .el-dialog__body{
  2355. background-color: #032046 !important;
  2356. }
  2357. ::v-deep .el-dialog .el-dialog__footer{
  2358. background-color: #032046 !important;
  2359. }
  2360. ::v-deep .el-tree-node__content > .el-tree-node__expand-icon{
  2361. padding: 3px !important;
  2362. }
  2363. </style>