|
@@ -0,0 +1,633 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div v-drag-window class="content infoModal-content">
|
|
|
|
|
+ <div class="content-title">
|
|
|
|
|
+ <div class="drag-title">
|
|
|
|
|
+ <span>{{ osdInfo.callsign }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <a class="fz16" style="color: white;" @click="() => osdInfo.visible = false">
|
|
|
|
|
+ <CloseOutlined />
|
|
|
|
|
+ </a>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="content-osd">
|
|
|
|
|
+ <div class="content-osd-head">
|
|
|
|
|
+ <div class="content-osd-head-icon">
|
|
|
|
|
+ <div class="content-osd-head-icon-image">
|
|
|
|
|
+ <a-image :src="M30Src" :preview="false" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <a-tooltip :title="osdInfo.model">
|
|
|
|
|
+ <div class="content-osd-head-icon-text">
|
|
|
|
|
+ {{ osdInfo.model }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-tooltip>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="content-osd-head-right">
|
|
|
|
|
+ <div class="content-osd-head-right-top">
|
|
|
|
|
+ <div class="content-osd-head-right-top-style">
|
|
|
|
|
+ 航线飞行
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="content-osd-head-right-top-status">
|
|
|
|
|
+ {{ getTextByModeCode(deviceInfo.device.mode_code) }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="content-osd-head-right-bottom">
|
|
|
|
|
+ <div class="content-osd-head-right-bottom-button">
|
|
|
|
|
+ <span class="openLiveButton" @click="state.deviceLiveStatus = true" v-if="!state.deviceLiveStatus">
|
|
|
|
|
+ 开启直播
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span class="openLiveButton" @click="state.deviceLiveStatus = false" v-else>
|
|
|
|
|
+ 关闭直播
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="content-osd-head-right-bottom-text">
|
|
|
|
|
+ 如需切换直播请停止后重新发起
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="content-osd-head-right-select">
|
|
|
|
|
+ <div v-if="state.deviceLiveStatus">
|
|
|
|
|
+ <a-select style="width: 130px;margin-right: 5px;" placeholder="摄像头" v-model:value="state.cameraValue">
|
|
|
|
|
+ <a-select-option v-for="item in state.cameraList" :key="item.value" :value="item.value"
|
|
|
|
|
+ @click="onCameraSelect(item)">
|
|
|
|
|
+ {{ item.label }}
|
|
|
|
|
+ </a-select-option>
|
|
|
|
|
+ </a-select>
|
|
|
|
|
+ <a-select style="width: 130px;margin-right: 5px;" placeholder="清晰度" v-model:value="state.clarityValue"
|
|
|
|
|
+ @select="onClaritySelect">
|
|
|
|
|
+ <a-select-option v-for="item in clarityList" :key="item.value" :value="item.value">
|
|
|
|
|
+ {{ item.label }}
|
|
|
|
|
+ </a-select-option>
|
|
|
|
|
+ </a-select>
|
|
|
|
|
+ <a-button style="margin-right: 5px;" :icon="h(PlaySquareOutlined)" @click="onStart" />
|
|
|
|
|
+ <a-button :icon="h(PoweroffOutlined)" @click="onStop" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="battery-slide">
|
|
|
|
|
+ <div style="background: #535759;" class="width-100"></div>
|
|
|
|
|
+ <div class="capacity-percent" :style="{ width: deviceInfo.device.battery.capacity_percent + '%' }"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <LivePlayer :text="state.playerText" :url="state.playerUrl" v-if="state.deviceLiveStatus" />
|
|
|
|
|
+ <div class="content-osd-info">
|
|
|
|
|
+ <a-row style="margin-bottom: 5px;">
|
|
|
|
|
+ <a-col span="6">
|
|
|
|
|
+ <div style="margin-top: -3px;" class="content-osd-info-item">
|
|
|
|
|
+ <a-tooltip title="遥控器信号">
|
|
|
|
|
+ <div style="display: flex;align-items: flex-end;">
|
|
|
|
|
+ <img style="margin-right: 5px;" :src="controllerSrc" v-if="controllerSignal > 0">
|
|
|
|
|
+ <img style="margin-right: 5px;" :src="controllerErrorSrc" v-else>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <img :src="signalThreeSrc" v-if="controllerSignal <= 3">
|
|
|
|
|
+ <img :src="signalFourSrc" v-else-if="controllerSignal === 4">
|
|
|
|
|
+ <img :src="signalFiveSrc" v-else-if="controllerSignal === 5">
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-tooltip>
|
|
|
|
|
+ <a-tooltip title="飞行器信号">
|
|
|
|
|
+ <div style="display: flex;align-items: flex-end;">
|
|
|
|
|
+ <img style="width: 15px;margin-right: 5px;" :src="networkSrc" v-if="aircraftSignal > 0">
|
|
|
|
|
+ <img style="width: 15px;margin-right: 5px;" :src="networkErrorSrc" v-else>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <img :src="signalThreeSrc" v-if="aircraftSignal <= 3">
|
|
|
|
|
+ <img :src="signalFourSrc" v-else-if="aircraftSignal === 4">
|
|
|
|
|
+ <img :src="signalFiveSrc" v-else-if="aircraftSignal === 5">
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-tooltip>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-col>
|
|
|
|
|
+ <a-col span="6">
|
|
|
|
|
+ <div class="content-osd-info-item">
|
|
|
|
|
+ <a-tooltip title="RTK">
|
|
|
|
|
+ <div style="display: flex;align-items: center;margin-right: 5px;">
|
|
|
|
|
+ <img style="width: 24px;margin-right: 5px;" :src="rtkSrc" v-if="RTK > 0">
|
|
|
|
|
+ <img style="width: 24px; margin-right: 5px;" :src="rtkErrorSrc" v-else>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ {{ RTK }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-tooltip>
|
|
|
|
|
+ <a-tooltip title="GPS">
|
|
|
|
|
+ <div style="display: flex;align-items: center;">
|
|
|
|
|
+ <img style="margin-right: 5px;" :src="gpsSrc" v-if="GPS > 0">
|
|
|
|
|
+ <img style="margin-right: 5px;" :src="gpsErrorSrc" v-else>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ {{ GPS }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-tooltip>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-col>
|
|
|
|
|
+ <a-col span="6">
|
|
|
|
|
+ <a-tooltip title="电量">
|
|
|
|
|
+ <div class="content-osd-info-item">
|
|
|
|
|
+ <div style="margin-right: 5px;">
|
|
|
|
|
+ <!-- <img :src="batteryOneSrc" v-if="capacity >= 75">
|
|
|
|
|
+ <img :src="batteryTwoSrc" v-else-if="capacity >= 50 && capacity < 75">
|
|
|
|
|
+ <img :src="batteryThreeSrc" v-else-if="capacity >= 25 && capacity < 50">
|
|
|
|
|
+ <img :src="batteryFourSrc" v-else-if="capacity < 25"> -->
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ {{ capacity + '%' }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-tooltip>
|
|
|
|
|
+ </a-col>
|
|
|
|
|
+ <a-col span="6">
|
|
|
|
|
+ <a-tooltip title="风向速度">
|
|
|
|
|
+ <div class="content-osd-info-item">
|
|
|
|
|
+ <img style="margin-right: 5px;" :src="windSrc">
|
|
|
|
|
+ <div style="font-weight: bold;margin-right: 5px;">
|
|
|
|
|
+ W.S
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ {{ windSpeed }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-tooltip>
|
|
|
|
|
+ </a-col>
|
|
|
|
|
+ </a-row>
|
|
|
|
|
+ <a-row>
|
|
|
|
|
+ <a-col span="6">
|
|
|
|
|
+ <a-tooltip title="海拔高度">
|
|
|
|
|
+ <div class="content-osd-info-item">
|
|
|
|
|
+ <div style="font-weight: bold;margin-right: 5px;">
|
|
|
|
|
+ ASL
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ {{ ASL }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-tooltip>
|
|
|
|
|
+ </a-col>
|
|
|
|
|
+ <a-col span="6">
|
|
|
|
|
+ <a-tooltip title="离地高度">
|
|
|
|
|
+ <div class="content-osd-info-item">
|
|
|
|
|
+ <div style="font-weight: bold;margin-right: 5px;">
|
|
|
|
|
+ AGL
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ {{ AGL }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-tooltip>
|
|
|
|
|
+ </a-col>
|
|
|
|
|
+ <a-col span="6">
|
|
|
|
|
+ <a-tooltip title="水平速度">
|
|
|
|
|
+ <div class="content-osd-info-item">
|
|
|
|
|
+ <div style="font-weight: bold;margin-right: 5px;">
|
|
|
|
|
+ H.S
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ {{ HS }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-tooltip>
|
|
|
|
|
+ </a-col>
|
|
|
|
|
+ <a-col span="6">
|
|
|
|
|
+ <a-tooltip title="当前高度">
|
|
|
|
|
+ <div class="content-osd-info-item">
|
|
|
|
|
+ <img style="margin-right: 5px;" :src="homeSrc">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ {{ homeDistance }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-tooltip>
|
|
|
|
|
+ </a-col>
|
|
|
|
|
+ </a-row>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script lang="ts" setup>
|
|
|
|
|
+import { h, computed, reactive, onMounted } from 'vue';
|
|
|
|
|
+import { message } from 'ant-design-vue';
|
|
|
|
|
+import { CloseOutlined, PlaySquareOutlined, PoweroffOutlined } from '@ant-design/icons-vue'
|
|
|
|
|
+import LivePlayer from '/@/components/livePlayer/index.vue';
|
|
|
|
|
+import M30Src from '/@/assets/icons/m30.png';
|
|
|
|
|
+import controllerSrc from '../icons/info/controller.svg';
|
|
|
|
|
+import controllerErrorSrc from '../icons/info/controllerError.svg';
|
|
|
|
|
+import networkSrc from '../icons/info/network.svg';
|
|
|
|
|
+import networkErrorSrc from '../icons/info/networkError.svg';
|
|
|
|
|
+import signalThreeSrc from '../icons/info/signalThree.svg';
|
|
|
|
|
+import signalFourSrc from '../icons/info/signalFour.svg';
|
|
|
|
|
+import signalFiveSrc from '../icons/info/signalFive.svg';
|
|
|
|
|
+import rtkSrc from '../icons/info/rtk.svg';
|
|
|
|
|
+import rtkErrorSrc from '../icons/info/rtkError.svg';
|
|
|
|
|
+import gpsSrc from '../icons/info/gps.svg';
|
|
|
|
|
+import gpsErrorSrc from '../icons/info/gpsError.svg';
|
|
|
|
|
+// import batteryOneSrc from '../icons/batteryOne.svg';
|
|
|
|
|
+// import batteryTwoSrc from '../icons/batteryTwo.svg';
|
|
|
|
|
+// import batteryThreeSrc from '../icons/batteryThree.svg';
|
|
|
|
|
+// import batteryFourSrc from '../icons/batteryFour.svg';
|
|
|
|
|
+import windSrc from '../icons/info/wind.svg';
|
|
|
|
|
+import homeSrc from '../icons/info/home.svg';
|
|
|
|
|
+import { CURRENT_CONFIG as config } from '/@/api/http/config';
|
|
|
|
|
+import { getLiveCapacity, startLivestream, stopLivestream } from '/@/api/manage';
|
|
|
|
|
+import { getTextByModeCode } from '/@/utils/index'
|
|
|
|
|
+
|
|
|
|
|
+interface Props {
|
|
|
|
|
+ osdInfo: any
|
|
|
|
|
+ deviceInfo: any
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+const props = withDefaults(defineProps<Props>(), {
|
|
|
|
|
+
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 遥控器信号
|
|
|
|
|
+const controllerSignal = computed(() => {
|
|
|
|
|
+ const info = props.deviceInfo.gateway;
|
|
|
|
|
+ if (info && info.wireless_link) {
|
|
|
|
|
+ return info.wireless_link['4g_gnd_quality'];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 飞机信号
|
|
|
|
|
+const aircraftSignal = computed(() => {
|
|
|
|
|
+ const info = props.deviceInfo.gateway;
|
|
|
|
|
+ if (info && info.wireless_link) {
|
|
|
|
|
+ return info.wireless_link['4g_uav_quality'];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const RTK = computed(() => {
|
|
|
|
|
+ const info = props.deviceInfo.device;
|
|
|
|
|
+ return info.position_state.rtk_number;
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const GPS = computed(() => {
|
|
|
|
|
+ const info = props.deviceInfo.device;
|
|
|
|
|
+ return info.position_state.gps_number;
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 电池容量
|
|
|
|
|
+const capacity = computed(() => {
|
|
|
|
|
+ const info = props.deviceInfo.device;
|
|
|
|
|
+ if (info) {
|
|
|
|
|
+ return info.battery.capacity_percent;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const windSpeed = computed(() => {
|
|
|
|
|
+ const info = props.deviceInfo.device;
|
|
|
|
|
+ if (info.wind_speed === '--') {
|
|
|
|
|
+ return info.wind_speed;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return (info.wind_speed / 10).toFixed(2) + ' m/s';
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const ASL = computed(() => {
|
|
|
|
|
+ const info = props.deviceInfo.device;
|
|
|
|
|
+ if (info.height === '--') {
|
|
|
|
|
+ return info.height;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return info.height.toFixed(2) + ' m';
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const AGL = computed(() => {
|
|
|
|
|
+ const info = props.deviceInfo.device;
|
|
|
|
|
+ if (info.elevation === '--') {
|
|
|
|
|
+ return info.elevation;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return info.elevation.toFixed(2) + ' m';
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const HS = computed(() => {
|
|
|
|
|
+ const info = props.deviceInfo.device;
|
|
|
|
|
+ if (info.horizontal_speed === '--') {
|
|
|
|
|
+ return info.horizontal_speed;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return info.horizontal_speed.toFixed(2) + ' m/s';
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+const homeDistance = computed(() => {
|
|
|
|
|
+ const info = props.deviceInfo.device;
|
|
|
|
|
+ if (info.home_distance === '--') {
|
|
|
|
|
+ return info.home_distance;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return info.home_distance.toFixed(2) + ' m';
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+interface SelectOption {
|
|
|
|
|
+ value: any,
|
|
|
|
|
+ label: string,
|
|
|
|
|
+ more?: any
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const clarityList: SelectOption[] = [
|
|
|
|
|
+ {
|
|
|
|
|
+ value: 0,
|
|
|
|
|
+ label: '自适应'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ value: 1,
|
|
|
|
|
+ label: '流畅'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ value: 2,
|
|
|
|
|
+ label: '标清'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ value: 3,
|
|
|
|
|
+ label: '高清'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ value: 4,
|
|
|
|
|
+ label: '超清'
|
|
|
|
|
+ }
|
|
|
|
|
+]
|
|
|
|
|
+
|
|
|
|
|
+interface State {
|
|
|
|
|
+ deviceLiveStatus: boolean,
|
|
|
|
|
+ cameraList: SelectOption[],
|
|
|
|
|
+ cameraValue?: string,
|
|
|
|
|
+ videoList: SelectOption[],
|
|
|
|
|
+ videoValue?: string,
|
|
|
|
|
+ clarityValue: number,
|
|
|
|
|
+ videoId: string,
|
|
|
|
|
+ playerText: string,
|
|
|
|
|
+ playerUrl: string,
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const state: State = reactive({
|
|
|
|
|
+ deviceLiveStatus: false,// 设备直播状态
|
|
|
|
|
+ cameraList: [],
|
|
|
|
|
+ cameraValue: undefined,
|
|
|
|
|
+ videoList: [],
|
|
|
|
|
+ videoValue: undefined,
|
|
|
|
|
+ clarityValue: 0,
|
|
|
|
|
+ videoId: '',
|
|
|
|
|
+ playerText: '',
|
|
|
|
|
+ playerUrl: '',
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const fetchLiveCapacity = async () => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await getLiveCapacity({});
|
|
|
|
|
+ if (res.code === 0) {
|
|
|
|
|
+ const deviceInfo = res.data.filter((item: any) => item.sn === props.osdInfo.sn)[0];
|
|
|
|
|
+ const cameras_list = deviceInfo.cameras_list || [];
|
|
|
|
|
+ const cameraList = cameras_list.map((item: any) => {
|
|
|
|
|
+ return {
|
|
|
|
|
+ label: item.name,
|
|
|
|
|
+ value: item.index,
|
|
|
|
|
+ more: item.videos_list
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ state.cameraList = cameraList;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e: any) {
|
|
|
|
|
+ console.error(e);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+onMounted(async () => {
|
|
|
|
|
+ await fetchLiveCapacity()
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const onCameraSelect = (record: SelectOption) => {
|
|
|
|
|
+ state.cameraValue = record.value;
|
|
|
|
|
+ if (!record.more) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const videoList = record.more.map((ele: any) => {
|
|
|
|
|
+ return {
|
|
|
|
|
+ label: ele.type,
|
|
|
|
|
+ value: ele.index,
|
|
|
|
|
+ more: ele.switch_video_types
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ state.videoList = videoList;
|
|
|
|
|
+ if (videoList.length === 0) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const firstVideo: SelectOption = videoList[0];
|
|
|
|
|
+ state.videoValue = firstVideo.value;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const onClaritySelect = (value: any) => {
|
|
|
|
|
+ state.clarityValue = value;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const onStart = async () => {
|
|
|
|
|
+ const { cameraValue, videoValue } = state;
|
|
|
|
|
+ if (!cameraValue) {
|
|
|
|
|
+ return message.warn('请选择摄像头');
|
|
|
|
|
+ }
|
|
|
|
|
+ const videoId = `${props.osdInfo.sn}/${cameraValue}/${videoValue || 'normal-0'}`;
|
|
|
|
|
+ state.videoId = videoId;
|
|
|
|
|
+ const liveURL = config.rtmpURL;
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res = await startLivestream({
|
|
|
|
|
+ url: liveURL,
|
|
|
|
|
+ video_id: videoId,
|
|
|
|
|
+ url_type: 1,// RTMP
|
|
|
|
|
+ video_quality: state.clarityValue
|
|
|
|
|
+ });
|
|
|
|
|
+ if (res.code !== 0) {
|
|
|
|
|
+ state.playerText = res.message;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const playerUrl = res.data.url;
|
|
|
|
|
+ state.playerText = '';
|
|
|
|
|
+ state.playerUrl = playerUrl;
|
|
|
|
|
+ message.success('已开启直播');
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e: any) {
|
|
|
|
|
+ console.error(e);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const onStop = async () => {
|
|
|
|
|
+ const { cameraValue, videoValue } = state;
|
|
|
|
|
+ if (!cameraValue) {
|
|
|
|
|
+ return message.warn('请选择摄像头');
|
|
|
|
|
+ }
|
|
|
|
|
+ const videoId = `${props.osdInfo.sn}/${cameraValue}/${videoValue || 'normal-0'}`;
|
|
|
|
|
+ const res = await stopLivestream({
|
|
|
|
|
+ video_id: videoId,
|
|
|
|
|
+ });
|
|
|
|
|
+ if (res.code === 0) {
|
|
|
|
|
+ state.videoId = '';
|
|
|
|
|
+ state.playerUrl = '';
|
|
|
|
|
+ message.success('已停止直播');
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+.content {
|
|
|
|
|
+ width: 420px;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ border-radius: 4px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ // background-color: rgba(0, 0, 0, 0.8);
|
|
|
|
|
+ background-color: #232323;
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ left: 10px;
|
|
|
|
|
+ top: 10px;
|
|
|
|
|
+
|
|
|
|
|
+ &-title {
|
|
|
|
|
+ padding: 5px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ border: 1px solid #535759;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-osd {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+
|
|
|
|
|
+ &-head {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+
|
|
|
|
|
+ &-icon {
|
|
|
|
|
+ width: 80px;
|
|
|
|
|
+ padding: 5px;
|
|
|
|
|
+ background: #3d3d3d;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+
|
|
|
|
|
+ &-image {
|
|
|
|
|
+ width: 80%;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-text {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-right {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ padding: 5px;
|
|
|
|
|
+
|
|
|
|
|
+ &-top {
|
|
|
|
|
+ margin: 10px 0;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+
|
|
|
|
|
+ &-style {
|
|
|
|
|
+ width: 100px;
|
|
|
|
|
+ color: #2a994b;
|
|
|
|
|
+ border-right: 1px solid #535759;
|
|
|
|
|
+ margin-right: 5px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-status {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ padding-left: 5px;
|
|
|
|
|
+ background: #4a4d4e;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-bottom {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+
|
|
|
|
|
+ &-button {
|
|
|
|
|
+ width: 100px;
|
|
|
|
|
+ border-right: 1px solid #535759;
|
|
|
|
|
+ margin-right: 5px;
|
|
|
|
|
+
|
|
|
|
|
+ .openLiveButton {
|
|
|
|
|
+ padding: 2px 4px;
|
|
|
|
|
+ border: 1.5px solid #535759;
|
|
|
|
|
+ border-radius: 2px;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-text {
|
|
|
|
|
+ color: #535759;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-select {
|
|
|
|
|
+ margin: 10px 0 5px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &-info {
|
|
|
|
|
+ padding: 5px;
|
|
|
|
|
+
|
|
|
|
|
+ &-item {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+
|
|
|
|
|
+ img {
|
|
|
|
|
+ width: 13px;
|
|
|
|
|
+ height: 13px;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="scss">
|
|
|
|
|
+.infoModal-content {
|
|
|
|
|
+
|
|
|
|
|
+ // 修改按钮样式
|
|
|
|
|
+ .ant-btn {
|
|
|
|
|
+ color: #FFFFFF;
|
|
|
|
|
+ background: transparent;
|
|
|
|
|
+ border: 1px solid #535759;
|
|
|
|
|
+
|
|
|
|
|
+ &:hover {
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ background-color: transparent;
|
|
|
|
|
+ border-color: #535759;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &:focus {
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ background-color: transparent;
|
|
|
|
|
+ border-color: #535759;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .ant-select-selector {
|
|
|
|
|
+ color: #FFFFFF;
|
|
|
|
|
+ background: transparent !important;
|
|
|
|
|
+ border: 1px solid #535759 !important;
|
|
|
|
|
+ box-shadow: none !important;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .ant-select-arrow {
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .ant-select-dropdown {
|
|
|
|
|
+ background-color: transparent;
|
|
|
|
|
+
|
|
|
|
|
+ .ant-select-item {
|
|
|
|
|
+ background-color: #000000 !important;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+
|
|
|
|
|
+ &:hover {
|
|
|
|
|
+ background-color: #4a4a4a !important;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .ant-select-item-option-selected {
|
|
|
|
|
+ background-color: #3a3a3a;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|