Browse Source

摄像机 弹窗 功能 完善, UI 交互修改

wangqin
Joe 11 months ago
parent
commit
e498147220
  1. 5
      package.json
  2. 2
      ruoyi-ui/src/views/JiHeExpressway/components/Teleport.vue
  3. 31
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/AMapContainer/loadAMap.js
  4. 24
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/Camera/Descriptions.vue
  5. 16
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/Camera/index.vue
  6. 66
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/ControlCamera/index.vue
  7. 11
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/mixin.js
  8. 56
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/index.vue
  9. 142
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/buttonEvent.js
  10. 60
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/httpList.js
  11. 56
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/map.js
  12. 47
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/videoStream.js
  13. 3
      ruoyi-ui/src/views/JiHeExpressway/pages/Home/index.vue
  14. 3
      ruoyi-ui/src/views/JiHeExpressway/utils/common.js
  15. 52
      ruoyi-ui/src/views/JiHeExpressway/utils/enum.js

5
package.json

@ -0,0 +1,5 @@
{
"dependencies": {
"flv.js": "^1.6.2"
}
}

2
ruoyi-ui/src/views/JiHeExpressway/components/Teleport.vue

@ -21,7 +21,7 @@ export default {
this.queryParentDom.appendChild(this.addDom = this.$el);
},
beforeDestroy() {
if (!this.queryParentDom) return;
if (!this.queryParentDom || !this.queryParentDom.contains(this.addDom)) return;
this.queryParentDom.removeChild(this.addDom);
},

31
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/AMapContainer/loadAMap.js

@ -1,4 +1,5 @@
import AMapLoader from "@amap/amap-jsapi-loader";
// import { delay } from "@screen/utils/common";
let LoadAMap;
@ -6,20 +7,26 @@ export function loadAMap() {
if (LoadAMap) return LoadAMap;
try {
return AMapLoader.load({
key: "3b5479d9ad9f01d138fef5e70daed7bd", // 申请好的Web端开发者Key,首次调用 load 时必填
// key: "b8053e4abb974f8a4346209ff5af93e9", // 申请好的Web端开发者Key,首次调用 load 时必填
// version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
})
.then((AMap) => {
console.log("地图加载成功");
return new Promise(async (resolve, reject) => {
// await delay(1500);
return (LoadAMap = AMap);
AMapLoader.load({
key: "3b5479d9ad9f01d138fef5e70daed7bd", // 申请好的Web端开发者Key,首次调用 load 时必填
// key: "b8053e4abb974f8a4346209ff5af93e9", // 申请好的Web端开发者Key,首次调用 load 时必填
// version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
// plugins: ["AMap.MarkerCluster"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
plugins: ["AMap.MarkerClusterer"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
})
.catch((e) => {
console.log("地图加载失败", e);
});
.then((AMap) => {
console.log("地图加载成功");
resolve((LoadAMap = AMap));
})
.catch((e) => {
reject();
console.log("地图加载失败", e);
});
});
} catch (error) {
console.log(
"%c [ try catch 地图加载失败 ]-27-「loadAMap.js」",

24
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/Camera/Descriptions.vue

@ -3,21 +3,21 @@
<p class="desc-item">
<span>设备类型</span>
<span>
球机
{{ cameraType || '-' }}
<img src="@screen/images/dialog/icon-control.png">
</span>
</p>
<p class="desc-item">
<span>道路名称</span>
<span>G35济菏高速</span>
<span>{{ data.road || '-' }}</span>
</p>
<p class="desc-item">
<span>所属机构</span>
<span>山东高速济南发展公司</span>
<span>{{ data.deptName || '-' }}</span>
</p>
<p class="desc-item">
<span>设备桩号</span>
<span>K094+079</span>
<span>{{ data.pileNum || '-' }}</span>
</p>
<p class="desc-item">
<span>上行相机</span>
@ -35,7 +35,7 @@
</p>
<p class="desc-item singleline">
<span>设备状态</span>
<span :style="{ color: '#19E1B1' }">在线</span>
<span :style="{ color: statusEnum.color || '#19E1B1' }">{{ statusEnum.text }}</span>
</p>
<p class="desc-item singleline">
<span>状态更新时间:</span>
@ -45,8 +45,22 @@
</template>
<script>
import { CameraStatusEnum, CameraControlTypeEnum } from "@screen/utils/enum.js"
export default {
name: 'Descriptions',
props: {
data: {
type: Object,
default: () => ({})
}
},
data() {
return {
statusEnum: CameraStatusEnum[this.data.status] || {},
cameraType: CameraControlTypeEnum[this.data.ptzCtrl]?.text
}
}
}
</script>

16
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/Camera/index.vue

@ -1,16 +1,16 @@
<template>
<Dialog v-model="obverseVisible" title="摄像机 G35 K094+079 下行(可控)">
<Dialog v-model="obverseVisible" :title="dialogData.camName">
<div class="Camera">
<div class="icon-content">
<img src="@screen/images/dialog/icon-photo.png" />
<img src="@screen/images/dialog/icon-video.png" />
</div>
<div class="video-presentation"></div>
<video controls class="video-stream" ref="videoContainerRef" />
<ElTabs v-model="activeName" @tab-click="handleClickTabs" class="tabs">
<ElTabPane label="详细设计" name="first">
<Descriptions />
<Descriptions :data="dialogData" />
</ElTabPane>
<ElTabPane label="摄相机参数" name="second">摄相机参数</ElTabPane>
</ElTabs>
@ -26,6 +26,7 @@
<script>
import Dialog from "@screen/components/Dialog/index.vue";
import Button from "@screen/components/Buttons/Button.vue"
import { openVideoStream } from "@screen/pages/Home/components/RoadAndEvents/utils/videoStream.js"
import Descriptions from "./Descriptions.vue"
import { dialogDelayVisible } from "./../mixin"
@ -43,6 +44,11 @@ export default {
activeName: 'first'
}
},
mounted() {
this.$nextTick(() => {
openVideoStream(this.dialogData.camId, this.$refs.videoContainerRef)
})
},
methods: {
handleClickTabs() { }
}
@ -67,11 +73,11 @@ export default {
}
}
.video-presentation {
.video-stream {
width: 100%;
height: 216px;
margin-top: 10px;
background: #00ebc1;
// background: #00ebc1;
img {
width: 100%;

66
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/ControlCamera/index.vue

@ -14,13 +14,14 @@
<div class="btn">全屏</div>
</div>
</div>
<video controls class="videoStream" ref="videoContainerRef" />
</div>
<div class="content">
<div class="left">
<p class="desc-item">
<span>设备名称: </span>
<span>疲劳唤醒设备1</span>
<span>{{ dialogData.camName || '-' }}</span>
</p>
<p class="desc-item">
<span>设备编号: </span>
@ -29,42 +30,42 @@
<div>
<p class="desc-item">
<span>设备桩号: </span>
<span>k097+900</span>
<span>{{ dialogData.pileNum || '-' }}</span>
</p>
<p class="desc-item">
<span>方向: </span>
<span class="color1">菏泽</span>
<span class="color1">{{ cameraDirection || '-' }}</span>
</p>
</div>
<p class="desc-item">
<span>/纬度: </span>
<span>117.071152 / 35.910659</span>
<span>{{ dialogData.camLong || '-' }} / {{ dialogData.camLat || '-' }}</span>
</p>
<p class="desc-item">
<span>道路名称: </span>
<span>G35济菏告诉</span>
<span>{{ dialogData.road }}</span>
</p>
<p class="desc-item">
<span>道路名称: </span>
<span class="color1">正常</span>
<span>设备状态: </span>
<span class="color1">{{ statusEnum.text || '-' }}</span>
</p>
</div>
<div class="dash-line"></div>
<div class="right">
<div class="direction">
<img class="top" src="./images/top.svg">
<img class="right" src="./images/right.svg">
<img class="top" src="./images/top.svg" @click="controlClick(21)">
<img class="right" src="./images/right.svg" @click="controlClick(24)">
<div class="center"></div>
<img class="bottom" src="./images/bottom.svg">
<img class="left" src="./images/left.svg">
<img class="bottom" src="./images/bottom.svg" @click="controlClick(22)">
<img class="left" src="./images/left.svg" @click="controlClick(23)">
</div>
<div class="options">
<div v-for="item in options" :key="item.key">
<img src="./images/sub.svg">
<img src="./images/sub.svg" @click="controlClick(item.sub)">
<span>{{ item.label }}</span>
<img src="./images/add.svg">
<img src="./images/add.svg" @click="controlClick(item.add)">
</div>
</div>
</div>
@ -81,6 +82,10 @@
import Dialog from "@screen/components/Dialog/index.vue"
import Button from "@screen/components/Buttons/Button.vue"
import { dialogDelayVisible } from "./../mixin"
import { CameraStatusEnum, CameraDirectionEnum } from "@screen/utils/enum.js"
import { controlCamera } from "@screen/pages/Home/components/RoadAndEvents/utils/httpList.js"
import { throttle } from "lodash"
import { openVideoStream } from "@screen/pages/Home/components/RoadAndEvents/utils/videoStream.js"
export default {
name: 'ControlCamera',
@ -91,22 +96,40 @@ export default {
},
data() {
return {
statusEnum: CameraStatusEnum[this.dialogData.status] || {},
cameraDirection: CameraDirectionEnum[this.dialogData.camOrientation]?.text,
options: [
{
label: "变倍",
key: "zoom"
key: "zoom",
add: "12",
sub: "11"
},
{
label: "光圈",
key: "aperture"
key: "aperture",
add: "15",
sub: "16"
},
{
label: "聚焦",
key: "focus"
key: "focus",
add: "13",
sub: "14"
},
]
}
},
mounted() {
this.$nextTick(() => {
openVideoStream(this.dialogData.camId, this.$refs.videoContainerRef)
})
},
methods: {
controlClick: throttle(function (type) {
controlCamera(this.dialogData.camId, type)
}, 360)
}
}
</script>
@ -126,9 +149,18 @@ export default {
.camera-video {
position: relative;
flex: 1;
background-color: #19E1B1;
// background-color: #19E1B1;
.videoStream {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.control-btns {
z-index: 1;
position: absolute;
padding: 6px 9px;
width: 100%;

11
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/Dialogs/mixin.js

@ -1,9 +1,10 @@
export const dialogDelayVisible = {
// props: {
// visible: {
// default: false,
// },
// },
props: {
dialogData: {
type: Object,
default: () => ({}),
},
},
data() {
return {
visibleData: false,

56
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/index.vue

@ -11,12 +11,8 @@
<TransitionGroup name="fade-group" tag="div" class="tabs-content">
<div class="device-item" v-for="(item, index) in tabContentData" :key="item.id" @click="handleDevice(item)"
:style="getStart(index)">
<Transition name="fade">
<img v-if="!item.status" class="device-icon" key="normal"
:src="require(`@screen/images/layer/${active}/${item.title}.svg`)" />
<img v-else class="device-icon" key="fault"
:src="require(`@screen/images/layer/${active}/${item.title}${item.status}.svg`)" />
</Transition>
<div class="device-icon"
:style="{ backgroundImage: `url(${require(`@screen/images/layer/${active}/${item.title}${item.status}.svg`)})` }" />
<span>{{ item.title }}</span>
</div>
</TransitionGroup>
@ -32,14 +28,14 @@
<!-- <ControlCamera :data="cameraDialogConfig.data" :visible="cameraDialogConfig.visibleType === 0" /> -->
<!-- 摄像机 G35 K094+079 下行可控 枪机 可打开-->
<!-- <Camera :data="cameraDialogConfig.data" :visible="cameraDialogConfig.visibleType === 1" /> -->
<component :data="cameraDialogConfig.data" :is="cameraDialogConfig.component" @change="handleCameraChange" />
<component :dialogData="cameraDialogConfig.data" :is="cameraDialogConfig.component" @change="handleCameraChange" />
</div>
</template>
<script>
import { getLayerData } from "./utils/layerImages";
import { debounce } from "lodash";
import { eventMap } from "./utils/buttonEvent";
import { eventMap, cacheRemoveFunc } from "./utils/buttonEvent";
import ControlCamera from "./../Dialogs/ControlCamera/index.vue"
import Camera from "./../Dialogs/Camera/index.vue";
@ -58,15 +54,19 @@ export default {
// -
cameraDialogConfig: {
// 0 ControlCamera | 1 Camera
component: null,
data: null
// 0 ControlCamera | 1 Camera
component: void 0,
data: void 0,
// component: ControlCamera,
// data: {
// camId: "57937",
// }
}
}
},
inject: ['getMap'],
created() {
const defaultActive = 2;
const defaultActive = 0;
const layerData = getLayerData();
this.layerData = layerData;
@ -94,6 +94,10 @@ export default {
if (!mapIns) return;
for (const key in cacheRemoveFunc) {
cacheRemoveFunc[key]?.();
}
// mapIns.clearMap();
mapIns.getLayers().forEach((layer, index) => index > 1 && mapIns.remove(layer))
},
@ -121,7 +125,7 @@ export default {
<style lang='scss' scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity .36s;
transition: opacity .24s;
}
.fade-enter,
@ -131,7 +135,7 @@ export default {
.fade-group-enter-active,
.fade-group-leave-active {
transition: all 0.36s ease;
transition: all 0.24s ease;
}
.fade-group-enter-from,
@ -142,6 +146,7 @@ export default {
.fade-group-leave-active {
// transform: translateY(24px);
position: absolute !important;
overflow: hidden;
}
.RoadAndEvents {
@ -155,6 +160,7 @@ export default {
padding: 24px 18px;
padding-bottom: 15px;
overflow: hidden;
max-height: min-content;
.tabs-content {
margin-top: 15px;
@ -177,14 +183,30 @@ export default {
flex-direction: column;
align-items: center;
--height-svg: 24px;
--gap: 9px;
--gap: 12px;
padding-top: calc(var(--height-svg) + var(--gap));
.device-icon {
display: block;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
height: 24px;
height: 33px;
width: 100%;
background-repeat: no-repeat;
background-size: auto;
background-position: center;
transition: all .18s linear;
&::before {
content: "";
position: absolute;
width: 33px;
height: 33px;
border: 1px solid rgba(0, 209, 255, .5);
border-radius: 50%;
}
}
span {

142
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/buttonEvent.js

@ -1,14 +1,18 @@
import { axiosIns } from "@screen/utils/axios/auth.js";
import { Message } from "element-ui";
const PilePointJSON = require(`@screen/pages/Home/components/AMapContainer/data/lcz.json`);
import { setMarkerCluster } from "./map";
// 0 有 可控(球机)ControlCamera | 1 ⽆ 不可控(枪机)Camera
const cameraCtrlMap = {
0: "ControlCamera",
1: "Camera",
};
const cacheData = {
DriveTestEquipment_Camera: null,
export const cacheRemoveFunc = {
DriveTestEquipment_Camera_Remove: null,
};
export const eventMap = {
@ -18,15 +22,32 @@ export const eventMap = {
if (!mapIns) return Message.error("地图加载失败!");
// const { code, data } = await axiosIns
// .get("/system/camera/camList")
// // .get("/system/dept/camTreeselect")
// .catch(() => ({}));
const { code, data } = { code: 200 };
// {
// camId: "57937",
// camLat: "0",
// camLong: "0",
// camName: "G35 K055+565 (可控)",
// camOrientation: "2",
// camStatus: "0",
// camType: "1",
// deptId: "1751",
// deptName: "G35济菏改扩建",
// firmType: "2",
// pileNum: "K055+565",
// ptzCtrl: "0",
// road: "G35",
// status: "0",
// };
const { code, data } = await axiosIns
.get("/system/camera/camList")
// .get("/system/dept/camTreeselect")
.catch(() => ({}));
// const { code, data } = { code: 200 };
if (code != 200) return Message.error("摄像机加载失败!");
// cacheData.DriveTestEquipment_Camera?.clear();
cacheRemoveFunc.DriveTestEquipment_Camera_Remove?.();
const normal = require(`@screen/images/layer${item.id.replace(".", "")}`);
const fault = require(`@screen/images/layer${item.id.replace(
@ -34,85 +55,52 @@ export const eventMap = {
(data) => (data === "." ? "" : `${data}_fault`)
)}`);
const size = 42;
const markers = [];
const markerClick = (e) => {
const {
target: {
w: { extData },
},
} = e;
this.cameraDialogConfig = {
// 0 有(球机) 1 ⽆(枪机)
component: cameraCtrlMap[extData.ptzCtrl],
data: extData,
};
const iconOption = {
type: "image",
size: [size, size],
anchor: "center",
console.log(this.cameraDialogConfig);
};
const layer =
cacheData.DriveTestEquipment_Camera ||
(cacheData.DriveTestEquipment_Camera = new AMap.LabelsLayer({
zooms: [3, 20],
zIndex: 1000,
collision: false,
}));
mapIns.add(layer);
const fitViewOverlays = [];
[
{
camLong: 116.471814,
camLat: 39.995856,
status: 0,
camName: "名称1",
camId: "666",
ptzCtrl: 0,
},
{
camLong: 116.456474,
camLat: 39.991563,
status: 1,
camName: "名称2",
camId: "333",
ptzCtrl: 1,
},
].forEach((item) => {
iconOption.image = item.status ? fault : normal;
const labelMarker = new AMap.LabelMarker({
position: [item.camLong, item.camLat],
icon: { ...iconOption },
name: item.camId,
zooms: [3, 20],
zIndex: 36,
opacity: 1,
text: {
content: item.camName,
direction: "right",
offset: [(size / 2 + 18) * -1, (size / 2 + 12) * -1],
style: {
fontSize: 12,
fontWeight: "normal",
fillColor: "#fff",
strokeColor: "#fff",
strokeWidth: 1,
fold: true,
padding: "3, 6",
},
},
});
data.forEach((item) => {
const { lng, lat } = PilePointJSON[item.pileNum] || {};
fitViewOverlays.push(labelMarker);
if (!lat || !lng) return;
labelMarker.on("click", (e) => {
this.cameraDialogConfig = {
// 0 有(球机) 1 ⽆(枪机)
component: cameraCtrlMap[item.ptzCtrl],
data: item,
};
const marker = new AMap.Marker({
position: [lng, lat],
content: `<img style="width: 36px; height: 36px" src='${
item.status !== "0" ? fault : normal
}'>`,
offset: new AMap.Pixel(-15, -15),
extData: item,
clickable: true,
});
layer.add(labelMarker);
marker.on("click", markerClick);
markers.push(marker);
});
mapIns.setFitView(fitViewOverlays, false, [360, 360, 360, 360]);
const markerCluster = await setMarkerCluster(mapIns, markers);
cacheRemoveFunc.DriveTestEquipment_Camera_Remove = () =>
markerCluster.clearMarkers();
mapIns.setFitView(markers, false, [360, 360, 360, 360]);
},
async "路测设备/摄像机_close"() {
cacheData.DriveTestEquipment_Camera?.clear();
cacheRemoveFunc.DriveTestEquipment_Camera_Remove?.();
},
};

60
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/httpList.js

@ -0,0 +1,60 @@
import { Message } from "element-ui";
import { axiosIns } from "@screen/utils/axios/auth.js";
/**
*
* @param {string} camId 相机 ID
* @param {1 | 2 | 3} media 参数说明: 1: http+flv; 2: rtmp; 3: hls
* @returns
*/
export function getCameraStream(camId, media = 1) {
return axiosIns.post("/videoInfo/api/externalVideoStreaming", {
type: 1,
camId,
media,
});
}
/**
* 球机进行控制
* @param {string} camId 相机 ID
* @param {number} cmdType 12 /焦距变(倍率变)/
11 /焦距变(倍率变)/
13 /焦点前调/
14 /焦点后调/
15 /光圈扩/
16 /光圈缩/
21 /云台向上/
22 /云台向下/
23 /云台左转/
24 /云台右转/
50 /云台左上转/
51 /云台左下转/
52 /云台右上转/
53 /云台右下转/
8 /设置预置位/
39 /预置位/
49 /辅助开关开/
48 /辅助开关关/
51 /设置巡航起始点/
52 /设置巡航结束点/
53 /开始巡航/
54 /巡航/
(-1) //
99 /向动作停/
* @returns
*/
export function controlCamera(camId, cmdType) {
return axiosIns
.post("/videoInfo/api/PTZControl", {
msgType: 3,
camId,
cmdType,
})
.then((result) => {
if (result.code != 200) Message.error(`相机操作失败!`);
})
.catch((err) => {
Message.error(`相机操作失败!`);
});
}

56
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/map.js

@ -0,0 +1,56 @@
import { loadAMap } from "@screen/pages/Home/components/AMapContainer/loadAMap.js";
/**
* @typedef {Object} Point
* @property {number} weight - The weight of the item.
* @property {number[]} lngLat - The longitude and latitude coordinates.
* @property {string} name - The name of the item.
* @property {string} icon - The icon of the item.
* @property {Object} extData - The icon of the item.
* @property {*} [x] - Additional properties of the item.
*/
/**
* https://lbs.amap.com/api/javascript-api-v2/documentation#markercluster 2.x
* https://lbs.amap.com/demo/javascript-api/example/marker/markerclusterer 1.x
* @param {*} map
* @param {Point[]} points
* @param {Marker[]} markers
* @param {*} options
* @returns
*/
export async function setMarkerCluster(map, markers, options) {
const AMap = await loadAMap();
return new AMap.MarkerClusterer(map, markers, {
// gridSize: 15,
maxZoom: 15,
...options,
// 自定义聚合点样式
renderClusterMarker(context) {
// 聚合中点个数
const clusterCount = context.count;
const div = document.createElement("div");
let bgColor = "204,235,197";
div.style.backgroundColor = `rgba(${bgColor}, .5)`;
const size = Math.round(
25 + Math.pow(clusterCount / markers.length, 1 / 5) * 36
);
div.style.borderRadius =
div.style.lineHeight =
div.style.width =
div.style.height =
`${size}px`;
div.style.border = `solid 1px rgba(${bgColor}, 1)`;
div.innerHTML = context.count;
div.style.color = "#ffffff";
div.style.fontSize = "24px";
div.style.textAlign = "center";
context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2));
context.marker.setContent(div);
},
});
}

47
ruoyi-ui/src/views/JiHeExpressway/pages/Home/components/RoadAndEvents/utils/videoStream.js

@ -0,0 +1,47 @@
import flvJs from "flv.js";
import { getCameraStream } from "./httpList";
/**
*
* @param {string} camId 相机ID
* @param {HTMLElement} container 容器
* @param {DPlayerOptions?} options 配置项
* @returns
*/
export async function openVideoStream(camId, container) {
const { code, data } = await getCameraStream(camId).catch(() => ({}));
if (code != 200) return;
const flvPlayer = flvJs.createPlayer({
type: "flv",
url: data.liveUrl,
isLive: true,
hasVideo: true,
hasAudio: true,
});
console.log(
"%c [ flvPlayer ]-26-「videoStream.js」",
"font-size:15px; background:#b2b540; color:#f6f984;",
flvPlayer
);
flvPlayer.attachMediaElement(container);
flvPlayer.load();
flvPlayer.play();
return flvPlayer;
// return new DPlayer({
// container,
// autoplay: true,
// ...options,
// hotkey: false,
// video: {
// url: data.liveUrl,
// type: "hls",
// // type: "flv",
// },
// });
}

3
ruoyi-ui/src/views/JiHeExpressway/pages/Home/index.vue

@ -97,6 +97,8 @@ export default {
display: flex;
flex-direction: column;
gap: 24px;
overflow: hidden;
height: 100%;
>div {
pointer-events: all;
@ -105,6 +107,7 @@ export default {
.content-l-b {
height: 332px;
max-height: 332px;
flex: 0.81;
}
}

3
ruoyi-ui/src/views/JiHeExpressway/utils/common.js

@ -0,0 +1,3 @@
export function delay(ms = 240) {
return new Promise((resolve) => setTimeout(() => resolve(void 0), ms));
}

52
ruoyi-ui/src/views/JiHeExpressway/utils/enum.js

@ -0,0 +1,52 @@
/**
* color: 颜色
* text: 文字
* icon: 展示的图标
*/
// 相机的状态
export const CameraStatusEnum = {
"-1": {
color: "",
text: "未启用",
},
0: {
color: "",
text: "正常",
},
1: {
color: "",
text: "网络中断",
},
2: {
color: "",
text: "网络正常无图像",
},
3: {
color: "",
text: "有图像, 图像存在问题",
},
};
// 摄像机方向
export const CameraDirectionEnum = {
0: {
text: "上行",
},
1: {
text: "下行",
},
2: {
text: "上下行 (双向)",
},
};
// 摄像 是否可控 是否有云台控制 0 有(球机) 1 ⽆(枪机)
export const CameraControlTypeEnum = {
0: {
text: "球机",
},
1: {
text: "枪机",
},
};
Loading…
Cancel
Save