| | |
| | | /* |
| | | * @Author: 胡思旗 931347610@qq.com |
| | | * @Date: 2023-08-22 09:55:39 |
| | | * @LastEditors: husq 931347610@qq.com |
| | | * @LastEditTime: 2023-09-13 19:01:16 |
| | | * @FilePath: \Cloud-API-Demo-Web\src\api\http\config.ts |
| | | * @Description: |
| | | * |
| | | * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved. |
| | | */ |
| | | export const CURRENT_CONFIG = { |
| | | |
| | | // license |
| | | appId: 'Please enter the app id.', // You need to go to the development website to apply. |
| | | appId: '0a472a3b0f1543ab9e66d1ad4e6a91c8', // You need to go to the development website to apply. |
| | | appKey: 'Please enter the app key.', // You need to go to the development website to apply. |
| | | appLicense: 'Please enter the app license.', // You need to go to the development website to apply. |
| | | |
| | |
| | | baseURL: 'http://192.168.1.198:6789', // This url must end with "/". Example: 'http://192.168.1.1:6789/' |
| | | // ws://172.16.13.129:6789/api/v1/ws |
| | | // ws://192.168.1.198:1883/ |
| | | websocketURL: 'ws://192.168.1.198:8600/drone/api/v1/ws', // Example: 'ws://192.168.1.198:6789/api/v1/ws' |
| | | websocketURL: 'ws://192.168.1.198:6789/api/v1/ws', // Example: 'ws://192.168.1.198:6789/api/v1/ws' |
| | | |
| | | // livestreaming |
| | | // RTMP Note: This IP is the address of the streaming server. If you want to see livestream on web page, you need to convert the RTMP stream to WebRTC stream. |
| | |
| | | } |
| | | |
| | | // 获取在线设备信息 |
| | | export const getDeviceTopo = async function (params:any): Promise<IWorkspaceResponse<any>> { |
| | | const url = `${HTTP_PREFIX_MANAGE}/manage/device` |
| | | const result = await request.get(url, { params }) |
| | | export const getDeviceTopo = async function (workspace_id: string): Promise<IWorkspaceResponse<any>> { |
| | | const url = `${HTTP_PREFIX}/devices/${workspace_id}/devices` |
| | | const result = await request.get(url) |
| | | return result.data |
| | | } |
| | | |
| | |
| | | const root = getRoot() |
| | | const options = [ |
| | | { key: 0, label: '团队', path: '/' + ERouterName.TSA, icon: 'TeamOutlined' }, |
| | | // { key: 1, label: '直播', path: '/' + ERouterName.LIVESTREAM, icon: 'VideoCameraOutlined' }, |
| | | { key: 1, label: '直播', path: '/' + ERouterName.LIVESTREAM, icon: 'VideoCameraOutlined' }, |
| | | { key: 2, label: '标注', path: '/' + ERouterName.LAYER, icon: 'EnvironmentOutlined' }, |
| | | { key: 3, label: '媒体库', path: '/' + ERouterName.MEDIA, icon: 'PictureOutlined' }, |
| | | { key: 4, label: '航线库', path: '/' + ERouterName.WAYLINE, icon: 'NodeIndexOutlined' }, |
| | |
| | | <!-- |
| | | * @Author: husq 931347610@qq.com |
| | | * @Date: 2023-09-13 18:21:08 |
| | | * @LastEditors: husq 931347610@qq.com |
| | | * @LastEditTime: 2023-09-14 11:40:03 |
| | | * @FilePath: \Cloud-API-Demo-Web\src\pages\page-web\projects\components\DockConfig.vue |
| | | * @Description: |
| | | * |
| | | * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved. |
| | | --> |
| | | <template> |
| | | <div class="config_dock"> |
| | | <div class="w100 option flex-display"> |
| | |
| | | </div> |
| | | <div class="option-btn flex-display flex-justify-between"> |
| | | <div class="btn"> |
| | | <a-button type="primary" @click="videoControl = !videoControl" :class="{ unchecked: !videoControl }" |
| | | <a-button type="primary" @click="control" :class="{ unchecked: !videoControl }" |
| | | style="width: 100%;"> |
| | | <template #icon> |
| | | <VideoCameraOutlined /> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="video"> |
| | | <div class="video" v-if="videoControl"> |
| | | <!-- <div class="video-option"> |
| | | <a-tooltip title="关闭补光灯"></a-tooltip> |
| | | </div> --> |
| | | <video auto src="https://cdn.jsdelivr.net/gh/xdlumia/files/video-play/IronMan.mp4" |
| | | style="width: 100%;height: 200px;"></video> |
| | | style="width: 100%;height: 200px;" id="video-webrtc" ref="videowebrtc" controls class="mt20"></video> |
| | | </div> |
| | | <div class="w100 option flex-display aerial"> |
| | | <div class="option-left-icon flex-display"> |
| | |
| | | </div> |
| | | <div class="mb5 select-box flex-display flex-align-center"> |
| | | <span class="f10 label mr15">失联动作</span> |
| | | <a-select :dropdownMatchSelectWidth="false" class="select-style" :bordered="false" size="small" ref="select" |
| | | v-model:value="option.lose_connection" style="width: 60px" @change="handleChange"> |
| | | <a-select :dropdownMatchSelectWidth="false" class="select-style" :bordered="false" size="small" |
| | | ref="select" v-model:value="option.lose_connection" style="width: 60px" @change="handleChange"> |
| | | <a-select-option value="1">悬停</a-select-option> |
| | | <a-select-option value="2">返航</a-select-option> |
| | | <a-select-option value="3">继续执行</a-select-option> |
| | |
| | | |
| | | <script setup lang="ts"> |
| | | import { VideoCameraOutlined, RobotOutlined, ToolOutlined, CloudOutlined, ThunderboltOutlined, FundProjectionScreenOutlined, UploadOutlined, BoxPlotOutlined } from '@ant-design/icons-vue' |
| | | import Drawer from '/@/components/Drawer/Drawer.vue' |
| | | import { getLiveCapacity, setLivestreamQuality, startLivestream, stopLivestream } from '/@/api/manage' |
| | | import { message } from 'ant-design-vue' |
| | | import jswebrtc from '/@/vendors/jswebrtc.min.js' |
| | | import { CURRENT_CONFIG as config } from '/@/api/http/config' |
| | | const nonSwitchable = 'normal' |
| | | // 视频ref |
| | | const videowebrtc = ref(null) |
| | | // 是否显示视频 |
| | | const videoControl = ref(false) |
| | | // 是否显示操作 页面暂未加 |
| | | const optionControl = ref(false) |
| | | // 一键起飞操作 |
| | | const flyControl = ref(false) |
| | | // 操作设置 |
| | | const option = ref({ |
| | | safe_height: 60, |
| | | fly_height: 60, |
| | |
| | | }) |
| | | const handleChange = (e: string) => { |
| | | console.log(e, 'eee') |
| | | } |
| | | // 画质设置 |
| | | interface SelectOption { |
| | | value: any, |
| | | label: string, |
| | | more?: any |
| | | } |
| | | const clarityList: SelectOption[] = [ |
| | | { |
| | | value: 0, |
| | | label: 'Adaptive' |
| | | }, |
| | | { |
| | | value: 1, |
| | | label: 'Smooth' |
| | | }, |
| | | { |
| | | value: 2, |
| | | label: 'Standard' |
| | | }, |
| | | { |
| | | value: 3, |
| | | label: 'HD' |
| | | }, |
| | | { |
| | | value: 4, |
| | | label: 'Super Clear' |
| | | } |
| | | ] |
| | | // 视频配置 |
| | | const videoOption = ref({ |
| | | url_type: 3, |
| | | url: '', |
| | | video_id: '', |
| | | video_quality: 3, |
| | | }) |
| | | const control = () => { |
| | | videoControl.value = !videoControl.value |
| | | if (videoControl.value) { |
| | | onStart() |
| | | } else { |
| | | onPause() |
| | | } |
| | | } |
| | | // 开启视频直播 |
| | | const onStart = async () => { |
| | | videoOption.value.video_id = `${'设备id'}/${'默认设备第一个相机id'}/${nonSwitchable}-0` |
| | | const liveURL = `serverIP=${config.gbServerIp}&serverPort=${config.gbServerPort}&serverID=${config.gbServerId}&agentID=${config.gbAgentId}&agentPassword=${config.gbPassword}&localPort=${config.gbAgentPort}&channel=${config.gbAgentChannel}` |
| | | const res = await startLivestream({ |
| | | url: liveURL, |
| | | video_id: videoOption.value.video_id, |
| | | url_type: videoOption.value.url_type, |
| | | video_quality: videoOption.value.video_quality, |
| | | }) |
| | | if (res.code !== 0) return |
| | | const url = res.data.url |
| | | const videoElement = videowebrtc.value |
| | | message.loading({ |
| | | content: 'Loding...', |
| | | duration: 4, |
| | | onClose () { |
| | | const player = new jswebrtc.Player(url, { |
| | | video: videoElement, |
| | | autoplay: true, |
| | | onPlay: (obj: any) => { |
| | | console.log('start play livestream') |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | // 暂停直播 |
| | | const onPause = async () => { |
| | | stopLivestream({ |
| | | video_id: videoOption.value.video_id |
| | | }).then(res => { |
| | | if (res.code === 0) { |
| | | message.success(res.message) |
| | | console.log('stop play livestream') |
| | | } |
| | | }) |
| | | } |
| | | </script> |
| | | |
| | |
| | | background-color: hsla(0, 0%, 100%, .1); |
| | | } |
| | | } |
| | | }</style> |
| | | } |
| | | </style> |
| | |
| | | <a-menu-item> |
| | | <a @click="goEdit(item)">编辑</a> |
| | | </a-menu-item> |
| | | <a-menu-item> |
| | | <!-- <a-menu-item> |
| | | <a @click="editStatus(item)">归档</a> |
| | | </a-menu-item> |
| | | </a-menu-item> --> |
| | | <a-menu-item> |
| | | <a @click="deleteItem(item)">删除</a> |
| | | </a-menu-item> |
| | |
| | | store.commit('SET_POINT_LIST', []) |
| | | router.push({ |
| | | name: ERouterName.WORKSPACE, |
| | | query: { id: item.id }, |
| | | query: { id: item.id, workSpaceId: item.workspace_id }, |
| | | }) |
| | | } |
| | | const goCenter = (item:any, index:number) => { |
| | |
| | | <a-empty style="color: #fff;" :image="simpleImage" description="暂无数据" :image-style="{ height: '60px' }" /> |
| | | </div> |
| | | <div v-else class="fz12" style="color: white;"> |
| | | {{ onlineDocks.data }} |
| | | ========= |
| | | {{ dockInfo }} |
| | | <div v-for="dock in onlineDocks.data" :key="dock.sn" |
| | | style="background: #3c3c3c; height: 90px; margin-bottom: 10px;"> |
| | | <div style="border-radius: 2px; height: 100%; width: 100%;" |
| | | class="flex-row flex-justify-between flex-align-center"> |
| | | <div style="float: left; padding: 0px 5px 8px 8px; width: 88%"> |
| | | <!-- // 机场设备标题 --> |
| | | <div style="width: 80%; height: 30px; line-height: 30px; font-size: 16px;"> |
| | | <a-tooltip :title="`${dock.gateway.callsign} - ${dock.callsign ?? 'No Drone'}`"> |
| | | <div class="text-hidden" style="max-width: 200px;">{{ dock.gateway.callsign }} - {{ dock.callsign ?? |
| | | 'No Drone' }}</div> |
| | | </a-tooltip> |
| | | </div> |
| | | <!-- // 机场设备状态 --> |
| | | <div class="mt5 flex-align-center flex-row flex-justify-between" style="background: #595959;"> |
| | | <div class="flex-align-center flex-row"> |
| | | <span class="ml5 mr5"> |
| | | <RobotOutlined /> |
| | | </span> |
| | | 132 |
| | | <div class="font-bold text-hidden" style="max-width: 80px;" |
| | | :style="dockInfo[dock.gateway.sn] && dockInfo[dock.gateway.sn].basic_osd?.mode_code !== EDockModeCode.Disconnected ? 'color: #00ee8b' : 'color: red;'"> |
| | | {{ dockInfo[dock.gateway.sn] ? EDockModeCode[dockInfo[dock.gateway.sn].basic_osd?.mode_code] : |
| | | EDockModeCode[EDockModeCode.Disconnected] }} |
| | | {{ dockInfo[dock.gateway.sn] ? EDockModeText[dockInfo[dock.gateway.sn].basic_osd?.mode_code] : |
| | | EDockModeText[EDockModeCode.Disconnected] }} |
| | | </div> |
| | | </div> |
| | | <div class="mr5 flex-align-center flex-row" style="width: 85px; margin-right: 0; height: 18px;"> |
| | |
| | | <div v-else class="width-100" style="height: 90%; background: rgba(0, 0, 0, 0.35)"></div> |
| | | </div> |
| | | </div> |
| | | <!-- // 机场是否启动 --> |
| | | <div class="mt5 flex-align-center flex-row flex-justify-between" style="background: #595959;"> |
| | | <div class="flex-row"> |
| | | <span class="ml5 mr5"> |
| | |
| | | </template> |
| | | |
| | | <script lang="ts" setup> |
| | | import { styleDrawer } from './common/common' |
| | | import { useConnectWebSocket } from '/@/hooks/use-connect-websocket' |
| | | import { flyTo } from '/@/hooks/use-center-point' |
| | | import { computed, onMounted, reactive, ref, watch, WritableComputedRef } from 'vue' |
| | | import { EDeviceTypeName, ELocalStorageKey } from '/@/types' |
| | | import Drawer from '/@/components/Drawer/Drawer.vue' |
| | | import noData from '/@/assets/icons/no-data.png' |
| | | import { Empty } from 'ant-design-vue' |
| | | import rc from '/@/assets/icons/rc.png' |
| | | import { OnlineDevice, EModeCode, OSDVisible, EDockModeCode, DeviceOsd } from '/@/types/device' |
| | | import { OnlineDevice, EModeCode, OSDVisible, EDockModeCode, DeviceOsd, EDockModeText } from '/@/types/device' |
| | | import { useMyStore } from '/@/store' |
| | | import { getDeviceTopo, getUnreadDeviceHms, updateDeviceHms } from '/@/api/manage' |
| | | import { RocketOutlined, EyeInvisibleOutlined, EyeOutlined, RobotOutlined, DoubleRightOutlined } from '@ant-design/icons-vue' |
| | | import { EHmsLevel } from '/@/types/enums' |
| | | import { UranusMqtt } from '/@/mqtt/index' |
| | | import Drawer from '/@/components/Drawer/Drawer.vue' |
| | | import { styleDrawer } from './common/common' |
| | | import DockConfig from './components/DockConfig.vue' |
| | | |
| | | const showDrawer = ref(false) |
| | | const { appContext } = getCurrentInstance() |
| | | const global = appContext.config.globalProperties |
| | | const route = useRoute() |
| | | const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE |
| | | // const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE |
| | | const store = useMyStore() |
| | | const username = ref(localStorage.getItem(ELocalStorageKey.Username)) |
| | | const workspaceId = ref(localStorage.getItem(ELocalStorageKey.WorkspaceId)!) |
| | | const osdVisible = ref({} as OSDVisible) |
| | | const hmsVisible = new Map<string, boolean>() |
| | | const scorllHeight = ref() |
| | | const showDrawer = ref(false) |
| | | const onlineDevices = reactive({ |
| | | data: [] as OnlineDevice[] |
| | | }) |
| | | |
| | | const onlineDocks = reactive({ |
| | | data: [ |
| | | { |
| | | model: '我是model字段', |
| | | callsign: '我是callsign字段', |
| | | sn: '我是sn字段', |
| | | mode: '我是mode字段', |
| | | gateway: { |
| | | model: 'gateway.model', |
| | | callsign: 'gateway.callsign', |
| | | sn: '我是gateway.sn字段', |
| | | mode: '我是gateway.mode字段', |
| | | }, |
| | | payload: [ |
| | | { |
| | | index: 1, |
| | | model: '2', |
| | | control_source: 'A', |
| | | payload_sn: 'payload_sn', |
| | | payload_index: 'payload_index', |
| | | payload_name: 'payload_name', |
| | | }, |
| | | ] |
| | | }, |
| | | ] as unknown as OnlineDevice[] |
| | | data: [] as OnlineDevice[] |
| | | }) |
| | | |
| | | const deviceInfo = computed(() => store.state.deviceState.deviceInfo) |
| | |
| | | }) |
| | | |
| | | onMounted(() => { |
| | | // flyTo(global.$viewer, route.params.longitude as unknown as number, route.params.latitude as unknown as number) |
| | | // getOnlineTopo() |
| | | // setTimeout(() => { |
| | | // watch(() => store.state.deviceStatusEvent, |
| | | // data => { |
| | | // getOnlineTopo() |
| | | // if (data.deviceOnline.sn) { |
| | | // getUnreadHms(data.deviceOnline.sn) |
| | | // } |
| | | // }, |
| | | // { |
| | | // deep: true |
| | | // } |
| | | // ) |
| | | // getOnlineDeviceHms() |
| | | // }, 3000) |
| | | getOnlineTopo() |
| | | setTimeout(() => { |
| | | watch(() => store.state.deviceStatusEvent, |
| | | data => { |
| | | getOnlineTopo() |
| | | if (data.deviceOnline.sn) { |
| | | getUnreadHms(data.deviceOnline.sn) |
| | | } |
| | | }, |
| | | { |
| | | deep: true |
| | | } |
| | | ) |
| | | getOnlineDeviceHms() |
| | | }, 3000) |
| | | const element = document.getElementsByClassName('scrollbar').item(0) as HTMLDivElement |
| | | const parent = element?.parentNode as HTMLDivElement |
| | | scorllHeight.value = parent?.clientHeight - parent?.firstElementChild?.clientHeight |
| | |
| | | // const { data |
| | | } |
| | | // 监听ws 消息 |
| | | useConnectWebSocket(messageHandler) |
| | | // useConnectWebSocket(messageHandler) |
| | | function getOnlineTopo () { |
| | | getDeviceTopo(workspaceId.value).then((res) => { |
| | | if (res.code !== 0) { |
| | |
| | | } |
| | | |
| | | // 监听ws 消息 |
| | | // useConnectWebSocket(messageHandler) |
| | | useConnectWebSocket(messageHandler) |
| | | |
| | | </script> |
| | | <style lang="scss" scoped> |
| | |
| | | import { getLayers } from '/@/api/layer' |
| | | import { LayerType } from '/@/types/mapLayer' |
| | | import { WaylineFile } from '/@/types/wayline' |
| | | import getter from './getters' |
| | | import { DevicesCmdExecuteInfo } from '/@/types/device-cmd' |
| | | import map from './map' |
| | | import common from '/@/store/common' |
| | | |
| | | const initStateFunc = () => ({ |
| | | Layers: [ |
| | | { |
| | | name: '默认', |
| | | name: 'default', |
| | | id: '', |
| | | is_distributed: true, |
| | | elements: [], |
| | |
| | | type: 1 |
| | | }, |
| | | { |
| | | name: '共享', |
| | | name: 'share', |
| | | id: '', |
| | | is_distributed: true, |
| | | elements: [], |
| | |
| | | mutations, |
| | | actions, |
| | | modules: { |
| | | getter, |
| | | map, |
| | | common |
| | | map |
| | | }, |
| | | } |
| | | |
| | |
| | | M3E_Camera = '1-66-0' as any, |
| | | M3T_Camera = '1-67-0' as any, |
| | | } |
| | | |
| | | export enum EDockModeText { |
| | | '已断开连接' = -1, |
| | | '空闲' = 0, |
| | | '调试' = 1, |
| | | '远程调试' = 2, |
| | | '正在升级' = 3, |
| | | '工作中' = 4 |
| | | } |
| | | export enum EDockModeCode { |
| | | Disconnected = -1, |
| | | Idle, |
| | |
| | | _onMessage (msg: MessageEvent) { |
| | | const data = JSON.parse(msg.data) |
| | | this._messageHandler && this._messageHandler(data) |
| | | console.log('接受消息', msg) |
| | | // console.log('接受消息', msg) |
| | | } |
| | | |
| | | sendMessage = (message: WebSocketOptions): void => { |
| | |
| | | |
| | | export function getWebsocketUrl () { |
| | | const token: string = localStorage.getItem(ELocalStorageKey.Token) || '' as string |
| | | const url = CURRENT_CONFIG.websocketURL |
| | | // const url = CURRENT_CONFIG.websocketURL + '?Authorization=' + encodeURI(token) |
| | | // const url = CURRENT_CONFIG.websocketURL |
| | | const url = CURRENT_CONFIG.websocketURL + '?x-auth-token=' + encodeURI(token) |
| | | return url |
| | | } |
| | | |