From 8d5056b1c07a1ec5abe15b3610529b3143ce55c7 Mon Sep 17 00:00:00 2001 From: douyage Date: Wed, 12 Aug 2026 15:29:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=A7=86=E9=A2=91=E9=A2=84?= =?UTF-8?q?=E8=A7=88=E3=80=81=E5=8E=86=E5=8F=B2=E5=9B=9E=E6=94=BE=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=EF=BC=8C=E8=AE=BE=E7=BD=AE=E8=B7=AF=E7=94=B1=E6=89=93?= =?UTF-8?q?=E5=BC=80=E6=8C=87=E5=AE=9A=E7=9A=84=E7=95=8C=E9=9D=A2=EF=BC=8C?= =?UTF-8?q?=E8=A1=A5=E5=85=A8=E5=AF=BC=E8=88=AA=E7=9A=84=E5=B0=8F=E5=9B=BE?= =?UTF-8?q?=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 2 + .env.production | 2 + .env.staging | 2 + package.json | 1 + src/api/nvrVideo.js | 80 +++ src/assets/images/nav/nav-area.png | Bin 0 -> 490 bytes src/assets/images/nav/nav-base-data.png | Bin 0 -> 359 bytes src/assets/images/nav/nav-defect.png | Bin 0 -> 349 bytes src/assets/images/nav/nav-device.png | Bin 0 -> 542 bytes src/assets/images/nav/nav-home.png | Bin 0 -> 396 bytes src/assets/images/nav/nav-monitor.png | Bin 0 -> 472 bytes src/assets/images/nav/nav-patrol-plan.png | Bin 0 -> 379 bytes src/assets/images/nav/nav-patrol-report.png | Bin 0 -> 312 bytes src/assets/images/nav/nav-patrol-schedule.png | Bin 0 -> 450 bytes src/assets/images/nav/nav-patrol-task.png | Bin 0 -> 574 bytes .../images/nav/nav-site-implementation.png | Bin 0 -> 385 bytes src/assets/images/nav/nav-site.png | Bin 0 -> 474 bytes src/assets/images/nav/nav-system.png | Bin 0 -> 575 bytes src/assets/images/nav/nav-task-management.png | Bin 0 -> 459 bytes src/assets/images/nav/nav-video-playback.png | Bin 0 -> 541 bytes src/assets/images/nav/nav-video-preview.png | Bin 0 -> 367 bytes src/components/Breadcrumb/index.vue | 5 +- src/layout/components/AppMain.vue | 8 + src/layout/components/Sidebar/Item.vue | 33 +- src/layout/components/Sidebar/SidebarItem.vue | 6 +- src/layout/components/Sidebar/index.vue | 38 +- src/layout/components/TagsView/index.vue | 129 ++++- src/layout/index.vue | 19 +- src/router/index.js | 91 ++++ .../ImagePreviewZoomTemperature/index.vue | 2 +- .../cards/patrolReport/InspectionReporter.vue | 4 +- .../cards/patrolReport/patrolReportDetail.vue | 12 +- .../cards/site_management/site_management.vue | 2 +- .../cards/taskSummary/inspectionTask.vue | 8 +- src/views/point/site_management.vue | 2 +- src/views/video/HistoryPlayback.vue | 357 +++++++++++++ src/views/video/LivePreview.vue | 475 ++++++++++++++++++ src/views/video/components/NvrDeviceTree.vue | 186 +++++++ .../video/components/NvrStreamPlayer.vue | 154 ++++++ vue.config.js | 8 + 40 files changed, 1596 insertions(+), 30 deletions(-) create mode 100644 src/api/nvrVideo.js create mode 100644 src/assets/images/nav/nav-area.png create mode 100644 src/assets/images/nav/nav-base-data.png create mode 100644 src/assets/images/nav/nav-defect.png create mode 100644 src/assets/images/nav/nav-device.png create mode 100644 src/assets/images/nav/nav-home.png create mode 100644 src/assets/images/nav/nav-monitor.png create mode 100644 src/assets/images/nav/nav-patrol-plan.png create mode 100644 src/assets/images/nav/nav-patrol-report.png create mode 100644 src/assets/images/nav/nav-patrol-schedule.png create mode 100644 src/assets/images/nav/nav-patrol-task.png create mode 100644 src/assets/images/nav/nav-site-implementation.png create mode 100644 src/assets/images/nav/nav-site.png create mode 100644 src/assets/images/nav/nav-system.png create mode 100644 src/assets/images/nav/nav-task-management.png create mode 100644 src/assets/images/nav/nav-video-playback.png create mode 100644 src/assets/images/nav/nav-video-preview.png create mode 100644 src/views/video/HistoryPlayback.vue create mode 100644 src/views/video/LivePreview.vue create mode 100644 src/views/video/components/NvrDeviceTree.vue create mode 100644 src/views/video/components/NvrStreamPlayer.vue diff --git a/.env.development b/.env.development index 2f7e897..09664d8 100644 --- a/.env.development +++ b/.env.development @@ -7,5 +7,7 @@ ENV = 'development' # 若依管理系统/开发环境 VUE_APP_BASE_API = '/dev-api' +VUE_APP_NVR_API = '/nvr-api' + # 路由懒加载 VUE_CLI_BABEL_TRANSPILE_MODULES = true diff --git a/.env.production b/.env.production index 8188545..ec7891a 100644 --- a/.env.production +++ b/.env.production @@ -6,3 +6,5 @@ ENV = 'production' # 若依管理系统/生产环境 VUE_APP_BASE_API = '/prod-api' + +VUE_APP_NVR_API = 'http://192.168.1.86:28081' diff --git a/.env.staging b/.env.staging index 2d51ff0..013ebde 100644 --- a/.env.staging +++ b/.env.staging @@ -10,3 +10,5 @@ ENV = 'staging' # 若依管理系统/测试环境 VUE_APP_BASE_API = '/stage-api' + +VUE_APP_NVR_API = '/nvr-api' diff --git a/package.json b/package.json index 8fa91c9..4d87b20 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "flv.js": "^1.6.2", "fuse.js": "6.4.3", "highlight.js": "9.18.5", + "hls.js": "^1.5.17", "js-beautify": "1.13.0", "js-cookie": "3.0.1", "jsencrypt": "3.0.0-rc.1", diff --git a/src/api/nvrVideo.js b/src/api/nvrVideo.js new file mode 100644 index 0000000..39495c9 --- /dev/null +++ b/src/api/nvrVideo.js @@ -0,0 +1,80 @@ +import axios from 'axios' + +const nvr = axios.create({ + baseURL: process.env.VUE_APP_NVR_API || '/nvr-api', + timeout: 30000, + withCredentials: false +}) + +nvr.interceptors.response.use( + response => response, + error => { + const response = error.response + const data = response && response.data + const message = data && (data.message || data.msg) + const normalized = new Error(message || error.message || 'NVR 服务请求失败') + normalized.status = response && response.status + normalized.response = response + return Promise.reject(normalized) + } +) + +const data = promise => promise.then(response => response.data) +const uiBase = '/hik/nvr/playback/hls/ui' +const playbackBase = '/hik/nvr/playback/hls' + +export function getNvrConfig() { + return data(nvr.get(`${uiBase}/config`)) +} + +export function startLive(cameraCode) { + return data(nvr.post(`${uiBase}/actions/live/start`, { cameraCode, streamType: 1 })) +} + +export function getLiveStatus(cameraCode) { + return data(nvr.get(`${uiBase}/actions/live/status`, { params: { cameraCode }})) +} + +export function stopLive(cameraCode) { + return data(nvr.post(`${uiBase}/actions/live/stop`, { cameraCode })) +} + +export function controlPtz(payload) { + return data(nvr.post('/device/ptzcontrol', payload)) +} + +export function getPresetList(deviceCode, domainCode) { + return data(nvr.get(`/device/ptzpresetlist/${encodeURIComponent(deviceCode)}/${encodeURIComponent(domainCode)}`)) +} + +export function createPreset(payload) { + return data(nvr.post(`${uiBase}/actions/preset/create`, payload)) +} + +export function createSnapshot(deviceCode, domainCode) { + return data(nvr.get(`/platform/platformSnapshot/${encodeURIComponent(deviceCode)}/${encodeURIComponent(domainCode)}`)) +} + +export function downloadSnapshot(taskId) { + return nvr.get(`/platform/snapshot/${encodeURIComponent(taskId)}`, { responseType: 'blob' }) +} + +export function createPlaybackSession(payload) { + return data(nvr.post(`${uiBase}/sessions`, payload)) +} + +export function getPlaybackSession(sessionId) { + return data(nvr.get(`${playbackBase}/sessions/${encodeURIComponent(sessionId)}`)) +} + +export function controlPlayback(sessionId, payload) { + return data(nvr.post(`${uiBase}/sessions/${encodeURIComponent(sessionId)}/controls`, payload)) +} + +export function deletePlaybackSession(sessionId) { + return data(nvr.delete(`${playbackBase}/sessions/${encodeURIComponent(sessionId)}`)) +} + +export function downloadPlaybackClip(payload) { + return nvr.post('/hik/nvr/playback/clips/download', payload, { responseType: 'blob', timeout: 120000 }) +} diff --git a/src/assets/images/nav/nav-area.png b/src/assets/images/nav/nav-area.png new file mode 100644 index 0000000000000000000000000000000000000000..85112bab16724458206be5f17d26ae9b42e2ba5b GIT binary patch literal 490 zcmVNkl3_(opb7(PMyKIWMFb6lBt1_ks?xVTP{&jGEgJ~0}91d#6T&jttcBQmkSzB6e>R^jm?@J&6u6V%%-2DBGy`fE`T@43x7y8#9f95 z^yMU%OJ>(Hg9nR0^JZ6bW)sI!{;br%;GL-14LpxtP7YBEzuwcH**$|fFp&sPPV9W3 z`ZSwyQI1x<0;ZwnR|Vy`=5jn?g2LbP46$VfGOeKX8)3+ z+}8@tTzdbQI)oOnZWSAn8Jvba8-Z8hD&Y=TCrAZs$RHb~5qY2n>Y~QpijreKEmDu5 zTiEVLsRCBp6s;ts5S>_acfsrwXAOq{YaN`F#HI^|)ZR;y#ifCy| zDgvXnw}hKIlq$=2!`#t(Za~kN`!k_o7FpBEZH-@@>B>#%b0&~+$n~YFU+O<$G*=tv z#u7!WUk6|Clwj){o`2v~#T}!$>w2O$8#PQV>gfq~&m*qa;X=(r;|g4A^1jjBb;Xr+ z)+?vdh`z{)@OIwF`u;xv00960{lX}U00006Nkl zy-EW?7)8HX!Jn59UqbA~%F-W9tDTiiz}mvf#>!H`N-MVm=6Fx5&?|tE-^sgg;*) z+{T}L_1e=vG?+}V@nI?<4Kv{>ZQeNQMu*wz?npSeF)VholBHv1DXEE&7dAsZsy z1IzTaMJ$ZlZNniPar!&*v`NHUy^wa5ZY)X?S&^OlLZuX0k=N1^DM?vYzUC#8564+W@ckE;t@+L5q8o@ymlTDkBAK-*w6_Z3xbt}Sor`FArW>+ zd<>z*LPEqd@kp0nd3175pQ>}JZdLzp)MA!yHM<69;1rypUBLToX30jg!e+Aq;y(`J zzn~y#mLCNvU(%6DYw&7DT0z?&FC?D%DosbyBykFD3NPh(TpEZF9%wpvmX>a$`8)6^ zO`uPspM(FPoTd`E1TMvEA|CO{M)LAay59}q4VxickZ)7Cgf|4YGuhF>kUkoBK#UC_ zDPp}yW}(h3ugR?9Me4?x3{o|5ZjN-hE~WFN6SPabr_W|$sX>b8LWr|W>_;qv2gw)V zdiU8Nhd72Obf4baW9=MmAyWlq9dhdtszUM{wSFZp70RR7aHQ($2 g000I_L_t&o00@JyPUQq7cK`qY07*qoM6N<$f`+B^3IG5A literal 0 HcmV?d00001 diff --git a/src/assets/images/nav/nav-home.png b/src/assets/images/nav/nav-home.png new file mode 100644 index 0000000000000000000000000000000000000000..793c8285085cff5f9bfaccce2f794ec3606bd932 GIT binary patch literal 396 zcmV;70dxL|P)2vC7p)vsUs+jmuVq;?<+EO?FJIS9#eNuSZ_k q7ytnO|22x)hX4Qo21!IgR09C`Bb5NdjnlvY00006P)dA|PV{LdTphVaxE!s}mgU1ZXNr1`(%x(HDVwElw@7pD+5LNSyC zsq`0$m}`KPi<#B_ft18b^3be}V*9Ps;dq{dl$5j$Vov62nSErWdVbvAyVQJX_U4c; z_lI!i5T|>jYJ{=G#l%u~2xSG*64e2U<#F-rQ}`hz9MS{_V~~i&9A8#}Ea&% literal 0 HcmV?d00001 diff --git a/src/assets/images/nav/nav-patrol-plan.png b/src/assets/images/nav/nav-patrol-plan.png new file mode 100644 index 0000000000000000000000000000000000000000..2b26068edcd4ef7d698342f21b432d95948f7420 GIT binary patch literal 379 zcmV->0fhdEP) zyG{Z@7=_QjiLt@X*irBZ#;2gs7{o}WJQ-S{QDTe*Phork6AL<}BwQMP&e_XkrhtWH zzS-eimYLnnI_^I=?#n|^Co`Z4;Maj6d9GootU4JN%wjw;>yw8X`pl1stH>*kHNo93 z-A}sijTmY2@(hY>Rm`;x&^iMC*T6JJn!G$zPDzpB8TbD}PiF~8lSe&_r1)<3_hxp_ zbLzYSY4Spgi==qv-sEff=Hvc~ktUD%Fp^?W_gEyw53>okbMc$=Bv&*M=8zZgsxGV;L7YofJetIk5l%)h|@|3Bliu5R%`KQ_Z)oc+X z4fL4M$g?W)56~{p^vLTj25h#8W&FY?T(sEkk-Hjt%Br&g00960RMK}^00006Nkl- zy$%6E5XWb)pb*|b;WbnmLLwS8RCq2Q1riAr#d!d=Rz#xUAt)HXy*N3^orwRE!CStyM}63BA;hO^7PLtGNYYGWn*Yhte6tP!$k9)b|6rj7bog}?;3NV)!00030|LQn^&;S4c21!IgR09Bo*>?0T2+OSi0000< KMNUMnLSTaCl6oWn literal 0 HcmV?d00001 diff --git a/src/assets/images/nav/nav-patrol-schedule.png b/src/assets/images/nav/nav-patrol-schedule.png new file mode 100644 index 0000000000000000000000000000000000000000..47c9c006ba985568427d9cc4c15040632e7e2605 GIT binary patch literal 450 zcmV;z0X_bSP)~OD%i}8{1UIi^N6*@vl-8$t#FLIvafhn}9E%VqqbOpa#*x-qy~_LO3D@ zPd{fq+;AZg5^l0PyEEULiVXtLDT(3m6AbA@12sKY%fZxa!|P zDxLI1uARYVereV|HG3eYPs|?09pb8=|J9}EVu)t0QsW(N2Zi(7>^#(ah$sh+`>)NzXa1DT<#afFrNDKAOF#Nb&p- z@XY&b{xaTBoV9^N^^52+XTTlB*A!{~O~#C(%7xhr^R9>WE{-d+7U#Rb1)9V=k6huX zdW>>KGX=SbL-YLt7TGNKGrFFA==E25*Z6&V907JXlbZ8lS->P)i$d@ zPlSB|@?aj!m^AAEe>#A84!aLNmPqyA+#lg92u0!&s3)l!^3N@)>R75S1qG=FZW2K2 z7lIU1yuwNdaye;x)ND)A9_8;R7t8D#`CW7eYocDf;VP%FJI74VlzS z;xHZCIbXx?gB!r6!Mk%I1ZNWMo;8K!!r66p!cxt>Uek6d^Ro z1&XXtwU(Xx5%ds01UZu`vQh-civt-(wO~i3bwnwG5#kfDf9_4FBan>`nL&Uj?4hXyXh30RR8Gaqi{-000I_L_t&o0AX~^JE>oLqW}N^ M07*qoM6N<$f=s*l(f|Me literal 0 HcmV?d00001 diff --git a/src/assets/images/nav/nav-site-implementation.png b/src/assets/images/nav/nav-site-implementation.png new file mode 100644 index 0000000000000000000000000000000000000000..d74ab9e55b2d506207a711cba3555af06a6a0c68 GIT binary patch literal 385 zcmV-{0e=38P)UUL)hT ziwf7={Oo1U&e_>>W|v*AiEqRG5Ol!Dx_g(LIJu|-ns@4#$&6pF7;3_we)t9XjCl#v zPBA@G-?UZtDM&p??XGmf;$7t6_%?*Sn}48ofaV_0gw>?jWrvC2hKa@sg%oovR{<#k zx-^6I@~eOoQe8?}Lq6jeM>J@m87W3n3ggxmFi)4NV@?d?BU^5vhcaeFyr4x~S9s{b zm=VTPJaDbA8J<6>t+~f{TcN@M7&F4ybsPOG$PVjBGq}#1wjx**#iXi4nhv3QBA_1LJX1`IEfx0dWL8gLGwf?L&a%R2aPLe7DP05 zl-SSdTX~NdWh8sK_g-sl&pqc{BOCf;y02@zUjk>klEE(3HvbH?zeH=h9#kq}7X$b@?ocmo7s#YtCgG&OK5OLcMs1 zCMe4vvGg8IuWPnT9vQLTlV5vE;%v8^dm@jFSZ`xUYA8YR=Ky*L`4SrHz|4XFgnXTd zlexy7VuQ2fkrC@D`6KQ_$2iFbk48=)#QLQC5qHs|sKJ+Xff?_osRyB6JVZ%8`L!o{ z+v2MM%Hw7am}=k{)YOXy(&g*F5$Ddm@CzA)BDe*sK=-Dsz9?Nj`2LUz0ig<(KFmt$ zd7K^fpsGF~JYMKSeplhmm{;{3zYcLyci0Y@ydnRHh}V6d|4s#*1+c;a&MAiX1EJ%=P)NklN))+a#(TJ-V zF+o9}x0p~P{%6z^%$72-P)Z9-Unyl7*P{~gbuVIW7s%Dj=>aWk(4wNX@gor%1goHj zc@cd19dZ7B<_{rP1B-gVsx{VDv~~w!3bZla;N4{9a~ql4@OsGA2%1Ar8$M;NTew9K z%>JyK`J$8gkyZC;_ap~6FXU?G^ysw)+^z^(kOS}#)Zu`u2xmuk(eCR!( z_HMPF`3`LpW8*?8bQN(d;u`TJh9x0a!xwsp8}LnQ-2(joN5vj5Qa-~1M!Ogi+u5(GI z-RJAf@9c41$koj0(Q6HOTJ1+XhHQZrvpwhC8;|(JO`C+*L#{^98+!b5Th>-@GWUK( z%+ji2li63mS&Sc8^@NbCffXicf_v6jOOAV-IiS_G4wr~_moVJNeCBvWmzBG6HFJ7E zo7*`+8~tyjwO4dB0Df-|^Rt=-f8!4T009600iD7Z00006NklXrTOX<6m(nwC0d+RePjpy|O;u7q@Hajgc>`v06d#LN~ ztutRh+Xm}P^g3d&1}iWR{+9Sz1#7PE71CTov;WB9Dm(AKO9RvyhW-|NrT!)eMR2&( z@a@u99ky7zjQFB?MBHPOhhzFC?ydhw_x5oIHG1K9krqF9`lgYdcy+9*jr?G+U7b*aRn_1upV|u65%6^vzAgoxdWN6x0*@V#ajFjadXi zpuU3v6KDgzKgxa3io7B)Xg{~vm9y01Nng# zd8iP{5Akx>U*Wr*achHMn54vL;^m?zm?{wp$s2F3aX7ahOc%KSC;MHKg(zC#;RR*l%JsTo;)aEEbJK{LL%ya-R2z-g`sOZ+U!$lo-+k;Gk zFyF2XUuIn9R>GL9tA{B_YM;YyIrj2F7;fm6zpBQhrKY^rw;)Z&ldd$@aXiO1HzF7k$>O^|jWq|={FbW?~57Nr3u66Kv`vU*~|NobnjbZ=* f00v1!K~w_(uieNkV8_L600000NkvXXu0mjftC9Dm literal 0 HcmV?d00001 diff --git a/src/assets/images/nav/nav-video-preview.png b/src/assets/images/nav/nav-video-preview.png new file mode 100644 index 0000000000000000000000000000000000000000..d02ef2f2fef964f64699c6b9a95fbf3728234786 GIT binary patch literal 367 zcmV-#0g(QQP)F&l#VJI> z`0e5@cgb^aPxiMnv-7gE^MpnBhl2Y@m+Y$L3nt|_yMz*yGuY$&)ul0HT1)PEF0Y1U zN#_-_BE@zpQW1T#g)New@FOG=*HEsoCsF~7Fz=p2z7?e9zoJco;21l^Q%}%iM=u0e zJVd5dV=q(W7MZo?aLiC(1-TEZ7dSPm#kP;lZlWWD`%h`|$m|gR05l3jqaW%WbeTLp zC|xs$_=K;R(`$h%@+L|93D;Tifj*c$7r$k{EOe zWeWQ)us!3PhK&vklk`YTTKtJBh4McD00960(c8nE00006Nkl58 literal 0 HcmV?d00001 diff --git a/src/components/Breadcrumb/index.vue b/src/components/Breadcrumb/index.vue index c8e855e..e77313a 100644 --- a/src/components/Breadcrumb/index.vue +++ b/src/components/Breadcrumb/index.vue @@ -46,7 +46,7 @@ export default { matched = router.matched.filter(item => item.meta && item.meta.title) } // 判断是否为首页 - if (!this.isDashboard(matched[0])) { + if (!this.isPatrolWorkspace() && !this.isDashboard(matched[0])) { matched = [{ path: "/index", meta: { title: "首页" } }].concat(matched) } this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) @@ -85,6 +85,9 @@ export default { } this.$router.push(path) }, + isPatrolWorkspace() { + return this.$route.matched.some(route => route.meta && route.meta.patrolWorkspace) + }, titleFn(item, children) { let str = ""; let lang = localStorage.getItem("language"); diff --git a/src/layout/components/AppMain.vue b/src/layout/components/AppMain.vue index 07b87a1..e808486 100644 --- a/src/layout/components/AppMain.vue +++ b/src/layout/components/AppMain.vue @@ -66,6 +66,14 @@ export default { padding-top: 108px; } +.app-main.patrolWorkspace.hasTagsView { + height: calc(100vh - 40px); +} + +.fixed-header + .app-main.patrolWorkspace.hasTagsView { + padding-top: 40px; +} + diff --git a/src/router/index.js b/src/router/index.js index ea124f2..f57b2d9 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -61,6 +61,69 @@ export const constantRoutes = [ component: () => import('@/views/error/401'), hidden: true }, + { + path: '/inspection-workspace', + component: Layout, + redirect: '/inspection-workspace/task', + hidden: true, + children: [ + { + path: 'task', + component: () => import('@/views/cards/taskSummary/inspectionTask'), + name: 'InspectionWorkspaceTask', + meta: { title: '巡视任务', activeMenu: '/inspection-workspace/task', patrolWorkspace: true } + }, + { + path: 'plan', + component: () => import('@/views/cards/patrolPlan/notstart'), + name: 'InspectionWorkspacePlan', + meta: { title: '巡视方案', activeMenu: '/inspection-workspace/plan', patrolWorkspace: true } + }, + { + path: 'points', + component: () => import('@/views/cards/site_management/site_management'), + name: 'InspectionWorkspacePoints', + meta: { title: '点位管理', activeMenu: '/inspection-workspace/points', patrolWorkspace: true } + }, + { + path: 'report', + component: () => import('@/views/cards/patrolReport/InspectionReporter'), + name: 'InspectionWorkspaceReport', + meta: { title: '巡视报告', activeMenu: '/inspection-workspace/report', patrolWorkspace: true } + }, + { + path: 'report/detail', + component: () => import('@/views/cards/patrolReport/patrolReportDetail'), + name: 'InspectionWorkspaceReportDetail', + hidden: true, + meta: { title: '巡视报告详情', activeMenu: '/inspection-workspace/report', patrolWorkspace: true } + }, + { + path: 'schedule', + component: () => import('@/views/cards/tasksShow/index'), + name: 'InspectionWorkspaceSchedule', + meta: { title: '巡视计划', activeMenu: '/inspection-workspace/schedule', patrolWorkspace: true } + }, + { + path: 'defects', + component: () => import('@/views/cards/defectRecord/index'), + name: 'InspectionWorkspaceDefects', + meta: { title: '缺陷记录', activeMenu: '/inspection-workspace/defects', patrolWorkspace: true } + }, + { + path: 'video-preview', + component: () => import('@/views/video/LivePreview'), + name: 'InspectionWorkspaceVideoPreview', + meta: { title: '视频预览', activeMenu: '/inspection-workspace/video-preview', patrolWorkspace: true } + }, + { + path: 'video-playback', + component: () => import('@/views/video/HistoryPlayback'), + name: 'InspectionWorkspaceVideoPlayback', + meta: { title: '历史回放', activeMenu: '/inspection-workspace/video-playback', patrolWorkspace: true } + } + ] + }, { path: '', component: Layout, @@ -181,6 +244,34 @@ export const constantRoutes = [ meta: { title: '缺陷记录', activeMenu: '/defect-record' } } ] + }, + { + path: '/video-preview', + component: Layout, + redirect: '/video-preview/index', + meta: { title: '视频预览' }, + children: [ + { + path: 'index', + component: () => import('@/views/video/LivePreview'), + name: 'VideoLivePreview', + meta: { title: '视频预览', activeMenu: '/video-preview' } + } + ] + }, + { + path: '/video-playback', + component: Layout, + redirect: '/video-playback/index', + meta: { title: '历史回放' }, + children: [ + { + path: 'index', + component: () => import('@/views/video/HistoryPlayback'), + name: 'VideoHistoryPlayback', + meta: { title: '历史回放', activeMenu: '/video-playback' } + } + ] } ] diff --git a/src/views/cards/components/ImagePreviewZoomTemperature/index.vue b/src/views/cards/components/ImagePreviewZoomTemperature/index.vue index 2892400..fa00bfe 100644 --- a/src/views/cards/components/ImagePreviewZoomTemperature/index.vue +++ b/src/views/cards/components/ImagePreviewZoomTemperature/index.vue @@ -31,7 +31,7 @@ --> diff --git a/src/views/video/HistoryPlayback.vue b/src/views/video/HistoryPlayback.vue new file mode 100644 index 0000000..6495314 --- /dev/null +++ b/src/views/video/HistoryPlayback.vue @@ -0,0 +1,357 @@ + + + + + diff --git a/src/views/video/LivePreview.vue b/src/views/video/LivePreview.vue new file mode 100644 index 0000000..d4c127d --- /dev/null +++ b/src/views/video/LivePreview.vue @@ -0,0 +1,475 @@ + + + + + diff --git a/src/views/video/components/NvrDeviceTree.vue b/src/views/video/components/NvrDeviceTree.vue new file mode 100644 index 0000000..bfd1cef --- /dev/null +++ b/src/views/video/components/NvrDeviceTree.vue @@ -0,0 +1,186 @@ + + + + + diff --git a/src/views/video/components/NvrStreamPlayer.vue b/src/views/video/components/NvrStreamPlayer.vue new file mode 100644 index 0000000..a04742d --- /dev/null +++ b/src/views/video/components/NvrStreamPlayer.vue @@ -0,0 +1,154 @@ + + + + + diff --git a/vue.config.js b/vue.config.js index 53cd73a..0d46ee5 100644 --- a/vue.config.js +++ b/vue.config.js @@ -34,7 +34,15 @@ module.exports = { host: '0.0.0.0', port: port, open: true, + historyApiFallback: true, proxy: { + '/nvr-api': { + target: 'http://192.168.1.86:28081', + changeOrigin: true, + pathRewrite: { + '^/nvr-api': '' + } + }, // detail: https://cli.vuejs.org/config/#devserver-proxy [process.env.VUE_APP_BASE_API]: { // target: `http://localhost:8080`,