| | |
| | | begin_time: number, |
| | | end_time: number, |
| | | message: string, |
| | | domain: string, |
| | | domain: number, |
| | | } |
| | | |
| | | export const login = async function (body: LoginBody): Promise<IWorkspaceResponse<any>> { |
| | |
| | | * @param domain |
| | | * @returns |
| | | */ |
| | | export const getBindingDevices = async function (workspace_id: string, body: IPage, domain: string): Promise<IListWorkspaceResponse<Device>> { |
| | | export const getBindingDevices = async function (workspace_id: string, body: IPage, domain: number): Promise<IListWorkspaceResponse<Device>> { |
| | | const url = `${HTTP_PREFIX}/devices/${workspace_id}/devices/bound?&page=${body.page}&page_size=${body.page_size}&domain=${domain}` |
| | | const result = await request.get(url) |
| | | return result.data |
| | |
| | | const url = `${HTTP_PREFIX}/workspaces/${workspaceId}/firmwares/${firmwareId}` |
| | | const result = await request.put(url, param) |
| | | return result.data |
| | | } |
| | | } |
| | |
| | | dock_name: string, |
| | | workspace_id: string, |
| | | username: string, |
| | | execute_time: string, |
| | | begin_time: string, |
| | | end_time: string, |
| | | execute_time: string, |
| | | completed_time: string, |
| | | status: TaskStatus, // 任务状态 |
| | | progress: number, // 执行进度 |
| | | code: number, // 错误码 |
| | |
| | | <span><a class="fz16" style="color: white;" @click="() => osdVisible.visible = false"><CloseOutlined /></a></span> |
| | | </div> |
| | | <div style="height: 82%;"> |
| | | <div class="flex-column flex-align-center flex-justify-center" style="float: left; width: 60px; height: 100%; background: #2d2d2d;"> |
| | | <div class="flex-column flex-align-center flex-justify-center" style="margin-top: -5px; padding-top: 25px; float: left; width: 60px; background: #2d2d2d;"> |
| | | <a-tooltip :title="osdVisible.model"> |
| | | <div style="width: 90%;" class="flex-column flex-align-center flex-justify-center"> |
| | | <span><a-image :src="M30" :preview="false"/></span> |
| | |
| | | </div> |
| | | <div class="osd flex-1" style="flex: 1"> |
| | | <a-row> |
| | | <a-col span="16" :style="deviceInfo.dock.mode_code === EDockModeCode.Disconnected ? 'color: red; font-weight: 700;': 'color: rgb(25,190,107)'"> |
| | | {{ EDockModeCode[deviceInfo.dock.mode_code] }}</a-col> |
| | | <a-col span="16" :style="deviceInfo.dock.basic_osd?.mode_code === EDockModeCode.Disconnected ? 'color: red; font-weight: 700;': 'color: rgb(25,190,107)'"> |
| | | {{ EDockModeCode[deviceInfo.dock.basic_osd?.mode_code] }}</a-col> |
| | | </a-row> |
| | | <a-row> |
| | | <a-col span="12"> |
| | | <a-tooltip title="Accumulated Running Time"> |
| | | <span><HistoryOutlined /></span> |
| | | <span class="ml10"> |
| | | <span v-if="deviceInfo.dock.acc_time >= 2592000"> {{ Math.floor(deviceInfo.dock.acc_time / 2592000) }}m </span> |
| | | <span v-if="(deviceInfo.dock.acc_time % 2592000) >= 86400"> {{ Math.floor((deviceInfo.dock.acc_time % 2592000) / 86400) }}d </span> |
| | | <span v-if="(deviceInfo.dock.acc_time % 2592000 % 86400) >= 3600"> {{ Math.floor((deviceInfo.dock.acc_time % 2592000 % 86400) / 3600) }}h </span> |
| | | <span v-if="(deviceInfo.dock.acc_time % 2592000 % 86400 % 3600) >= 60"> {{ Math.floor((deviceInfo.dock.acc_time % 2592000 % 86400 % 3600) / 60) }}min </span> |
| | | <span>{{ Math.floor(deviceInfo.dock.acc_time % 2592000 % 86400 % 3600 % 60) }} s</span> |
| | | <span v-if="deviceInfo.dock.work_osd?.acc_time >= 2592000"> {{ Math.floor(deviceInfo.dock.work_osd?.acc_time / 2592000) }}m </span> |
| | | <span v-if="(deviceInfo.dock.work_osd?.acc_time % 2592000) >= 86400"> {{ Math.floor((deviceInfo.dock.work_osd?.acc_time % 2592000) / 86400) }}d </span> |
| | | <span v-if="(deviceInfo.dock.work_osd?.acc_time % 2592000 % 86400) >= 3600"> {{ Math.floor((deviceInfo.dock.work_osd?.acc_time % 2592000 % 86400) / 3600) }}h </span> |
| | | <span v-if="(deviceInfo.dock.work_osd?.acc_time % 2592000 % 86400 % 3600) >= 60"> {{ Math.floor((deviceInfo.dock.work_osd?.acc_time % 2592000 % 86400 % 3600) / 60) }}min </span> |
| | | <span>{{ Math.floor(deviceInfo.dock.work_osd?.acc_time % 2592000 % 86400 % 3600 % 60) }} s</span> |
| | | </span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="12"> |
| | | <a-tooltip title="Last login"> |
| | | <a-tooltip title="Activation time"> |
| | | <span><FieldTimeOutlined /></span> |
| | | <span class="ml10">{{ new Date(deviceInfo.dock.first_power_on).toLocaleString() }} |
| | | <span class="ml10">{{ new Date((deviceInfo.dock.work_osd?.activation_time ?? 0) * 1000).toLocaleString() }} |
| | | </span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | </a-row> |
| | | <a-row> |
| | | <a-col span="12"> |
| | | <a-col span="6"> |
| | | <a-tooltip title="Network State"> |
| | | <span :style="deviceInfo.dock.network_state?.quality === 2 ? 'color: #00ee8b' : |
| | | deviceInfo.dock.network_state?.quality === 1 ? 'color: yellow' : 'color: red'"> |
| | | <span v-if="deviceInfo.dock.network_state?.type === 1"><SignalFilled /></span> |
| | | <span :style="deviceInfo.dock.basic_osd?.network_state?.type === NetworkStateTypeEnum.ETHERNET || deviceInfo.dock.basic_osd?.network_state?.quality === NetworkStateQualityEnum.GOOD ? |
| | | 'color: #00ee8b' : deviceInfo.dock.basic_osd?.network_state?.quality === NetworkStateQualityEnum.MEDIUM ? 'color: yellow' : 'color: red'"> |
| | | <span v-if="deviceInfo.dock.basic_osd?.network_state?.type === NetworkStateTypeEnum.FOUR_G"><SignalFilled /></span> |
| | | <span v-else><GlobalOutlined /></span> |
| | | </span> |
| | | <span class="ml10" >{{ deviceInfo.dock.network_state?.rate }} KB/S</span> |
| | | <span class="ml10" >{{ deviceInfo.dock.basic_osd?.network_state?.rate }} kb/s</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="6"> |
| | | <a-tooltip title="The total number of times the dock has performed missions."> |
| | | <span><CarryOutOutlined /></span> |
| | | <span class="ml10" >{{ deviceInfo.dock.work_osd?.job_number }} </span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="6"> |
| | | <a-tooltip title="Media File Remain Upload"> |
| | | <span><CloudUploadOutlined class="fz14"/></span> |
| | | <span class="ml10">{{ deviceInfo.dock.media_file_detail?.remain_upload }}</span> |
| | | <span class="ml10">{{ deviceInfo.dock.link_osd?.media_file_detail?.remain_upload }}</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="6"> |
| | | <a-tooltip> |
| | | <template #title> |
| | | <p>total: {{ deviceInfo.dock.storage?.total }}</p> |
| | | <p>used: {{ deviceInfo.dock.storage?.used }}</p> |
| | | <p>total: {{ deviceInfo.dock.basic_osd?.storage?.total }}</p> |
| | | <p>used: {{ deviceInfo.dock.basic_osd?.storage?.used }}</p> |
| | | </template> |
| | | <span><FolderOpenOutlined /></span> |
| | | <span class="ml10" v-if="deviceInfo.dock.storage?.total > 0"> |
| | | <a-progress type="circle" :width="20" :percent="deviceInfo.dock.storage?.used * 100/ deviceInfo.dock.storage?.total" |
| | | :strokeWidth="20" :showInfo="false" :strokeColor="deviceInfo.dock.storage?.used * 100 / deviceInfo.dock.storage?.total > 80 ? 'red' : '#00ee8b' "/> |
| | | <span class="ml10" v-if="deviceInfo.dock.basic_osd?.storage?.total > 0"> |
| | | <a-progress type="circle" :width="20" :percent="deviceInfo.dock.basic_osd?.storage?.used * 100/ deviceInfo.dock.basic_osd?.storage?.total" |
| | | :strokeWidth="20" :showInfo="false" :strokeColor="deviceInfo.dock.basic_osd?.storage?.used * 100 / deviceInfo.dock.basic_osd?.storage?.total > 80 ? 'red' : '#00ee8b' "/> |
| | | </span> |
| | | </a-tooltip> |
| | | </a-col> |
| | |
| | | <a-col span="6"> |
| | | <a-tooltip title="Wind Speed"> |
| | | <span>W.S</span> |
| | | <span class="ml10">{{ deviceInfo.dock.wind_speed === str ? str : (deviceInfo.dock.wind_speed / 10).toFixed(2) + ' m/s'}}</span> |
| | | <span class="ml10">{{ (deviceInfo.dock.basic_osd?.wind_speed ?? str) + ' m/s'}}</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="6"> |
| | | <a-tooltip title="Rainfall"> |
| | | <span>🌧</span> |
| | | <span class="ml10">{{ deviceInfo.dock.rainfall === str ? str : deviceInfo.dock.rainfall + ' mm/h' }}</span> |
| | | <span class="ml10">{{ RainfallEnum[deviceInfo.dock.basic_osd?.rainfall] }}</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="6"> |
| | | <a-tooltip title="Environment Temperature"> |
| | | <span>°C</span> |
| | | <span class="ml10">{{ deviceInfo.dock.environment_temperature }}</span> |
| | | <span class="ml10">{{ deviceInfo.dock.basic_osd?.environment_temperature }}</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="6"> |
| | | <a-tooltip title="Environment Humidity"> |
| | | <span>💦</span> |
| | | <span class="ml10">{{ deviceInfo.dock.environment_humidity === str ? str : deviceInfo.dock.environment_humidity }}</span> |
| | | <a-tooltip title="Dock Temperature"> |
| | | <span>°C</span> |
| | | <span class="ml10">{{ deviceInfo.dock.basic_osd?.temperature }}</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | </a-row> |
| | | <a-row> |
| | | <a-col span="6"> |
| | | <a-tooltip title="Dock Temperature"> |
| | | <span>°C</span> |
| | | <span class="ml10">{{ deviceInfo.dock.temperature }}</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="6"> |
| | | <a-tooltip title="Dock Humidity"> |
| | | <span>💦</span> |
| | | <span class="ml10">{{ deviceInfo.dock.humidity === str ? str : deviceInfo.dock.humidity }}</span> |
| | | <span class="ml10">{{ deviceInfo.dock.basic_osd?.humidity }}</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="6"> |
| | | <a-tooltip title="Working Voltage"> |
| | | <span style="border: 1px solid; border-radius: 50%; width: 18px; height: 18px; line-height: 16px; text-align: center; float: left;">V</span> |
| | | <span class="ml10">{{ deviceInfo.dock.working_voltage === str ? str : deviceInfo.dock.working_voltage + ' mV' }}</span> |
| | | <span class="ml10">{{ (deviceInfo.dock.work_osd?.working_voltage ?? str) + ' mV' }}</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="6"> |
| | | <a-tooltip title="Working Current"> |
| | | <span style="border: 1px solid; border-radius: 50%; width: 18px; height: 18px; line-height: 15px; text-align: center; float: left;" >A</span> |
| | | <span class="ml10">{{ deviceInfo.dock.working_current === str ? str : deviceInfo.dock.working_current + ' mA' }}</span> |
| | | <span class="ml10">{{ (deviceInfo.dock.work_osd?.working_current ?? str) + ' mA' }}</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="6"> |
| | | <a-tooltip title="Drone in dock"> |
| | | <span><RocketOutlined /></span> |
| | | <span class="ml10">{{ DroneInDockEnum[deviceInfo.dock.basic_osd?.drone_in_dock] }}</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | </a-row> |
| | |
| | | <a-col span="6"> |
| | | <a-tooltip title="Upward Quality"> |
| | | <span><SignalFilled /><ArrowUpOutlined style="font-size: 9px; vertical-align: top;" /></span> |
| | | <span class="ml10">{{ deviceInfo.dock.sdr?.up_quality }}</span> |
| | | <span class="ml10">{{ deviceInfo.dock.link_osd?.sdr?.up_quality }}</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="6"> |
| | | <a-tooltip title="Downward Quality"> |
| | | <span><SignalFilled /><ArrowDownOutlined style="font-size: 9px; vertical-align: top;" /></span> |
| | | <span class="ml10">{{ deviceInfo.dock.sdr?.down_quality }}</span> |
| | | <span class="ml10">{{ deviceInfo.dock.link_osd?.sdr?.down_quality }}</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="6"> |
| | | <a-tooltip title="Drone Battery Level"> |
| | | <span><ThunderboltOutlined class="fz14"/></span> |
| | | <span class="ml10">{{ deviceInfo.device && deviceInfo.device.battery.capacity_percent !== str ? deviceInfo.device?.battery.capacity_percent + ' %' : str }}</span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | <a-col span="6"> |
| | | <a-tooltip> |
| | | <template #title> |
| | | <p>total: {{ deviceInfo.device?.storage?.total }}</p> |
| | | <p>used: {{ deviceInfo.device?.storage?.used }}</p> |
| | | </template> |
| | | <span><FolderOpenOutlined /></span> |
| | | <span class="ml10" v-if="deviceInfo.device?.storage?.total > 0"> |
| | | <a-progress type="circle" :width="20" :percent="deviceInfo.device?.storage?.used * 100/ deviceInfo.device?.storage?.total" |
| | | :strokeWidth="20" :showInfo="false" :strokeColor="deviceInfo.device?.storage?.used * 100 / deviceInfo.device?.storage?.total > 80 ? 'red' : '#00ee8b' "/> |
| | | </span> |
| | | </a-tooltip> |
| | | </a-col> |
| | | </a-row> |
| | |
| | | import { useGMapManage } from '/@/hooks/use-g-map' |
| | | import { useGMapCover } from '/@/hooks/use-g-map-cover' |
| | | import { useMouseTool } from '/@/hooks/use-mouse-tool' |
| | | import { getApp } from '/@/root' |
| | | import { getApp, getRoot } from '/@/root' |
| | | import { useMyStore } from '/@/store' |
| | | import { GeojsonCoordinate } from '/@/types/map' |
| | | import { MapDoodleEnum } from '/@/types/map-enum' |
| | |
| | | import { uuidv4 } from '/@/utils/uuid' |
| | | import { gcj02towgs84, wgs84togcj02 } from '/@/vendors/coordtransform' |
| | | import { deviceTsaUpdate } from '/@/hooks/use-g-map-tsa' |
| | | import { DeviceOsd, DeviceStatus, DockOsd, EGear, EModeCode, GatewayOsd, EDockModeCode } from '/@/types/device' |
| | | import { |
| | | DeviceOsd, DeviceStatus, DockOsd, EGear, EModeCode, GatewayOsd, EDockModeCode, |
| | | NetworkStateQualityEnum, NetworkStateTypeEnum, RainfallEnum, DroneInDockEnum |
| | | } from '/@/types/device' |
| | | import pin from '/@/assets/icons/pin-2d8cf0.svg' |
| | | import M30 from '/@/assets/icons/m30.png' |
| | | import { |
| | | BorderOutlined, LineOutlined, CloseOutlined, ControlOutlined, TrademarkOutlined, ArrowDownOutlined, |
| | | ThunderboltOutlined, SignalFilled, GlobalOutlined, HistoryOutlined, CloudUploadOutlined, |
| | | FieldTimeOutlined, CloudOutlined, CloudFilled, FolderOpenOutlined, RobotFilled, ArrowUpOutlined |
| | | ThunderboltOutlined, SignalFilled, GlobalOutlined, HistoryOutlined, CloudUploadOutlined, RocketOutlined, |
| | | FieldTimeOutlined, CloudOutlined, CloudFilled, FolderOpenOutlined, RobotFilled, ArrowUpOutlined, CarryOutOutlined |
| | | } from '@ant-design/icons-vue' |
| | | import { EDeviceTypeName } from '../types' |
| | | import DockControlPanel from './g-map/DockControlPanel.vue' |
| | |
| | | RobotFilled, |
| | | ArrowUpOutlined, |
| | | ArrowDownOutlined, |
| | | DockControlPanel |
| | | DockControlPanel, |
| | | CarryOutOutlined, |
| | | RocketOutlined |
| | | }, |
| | | name: 'GMap', |
| | | props: {}, |
| | |
| | | const useMouseToolHook = useMouseTool() |
| | | const useGMapManageHook = useGMapManage() |
| | | const deviceTsaUpdateHook = ref() |
| | | const root = getRoot() |
| | | |
| | | const mouseMode = ref(false) |
| | | const store = useMyStore() |
| | |
| | | transmission_signal_quality: str, |
| | | } as GatewayOsd, |
| | | dock: { |
| | | media_file_detail: { |
| | | remain_upload: 0 |
| | | }, |
| | | sdr: { |
| | | up_quality: str, |
| | | down_quality: str, |
| | | frequency_band: -1, |
| | | }, |
| | | network_state: { |
| | | type: 0, |
| | | quality: 0, |
| | | rate: 0, |
| | | }, |
| | | drone_in_dock: 0, |
| | | drone_charge_state: { |
| | | state: 0, |
| | | capacity_percent: str, |
| | | }, |
| | | rainfall: str, |
| | | wind_speed: str, |
| | | environment_temperature: str, |
| | | environment_humidity: str, |
| | | temperature: str, |
| | | humidity: str, |
| | | job_number: 0, |
| | | acc_time: 0, |
| | | first_power_on: 0, |
| | | positionState: { |
| | | gps_number: str, |
| | | is_fixed: 0, |
| | | rtk_number: str, |
| | | is_calibration: 0, |
| | | quality: 0, |
| | | }, |
| | | storage: { |
| | | total: 0, |
| | | used: 0, |
| | | }, |
| | | electric_supply_voltage: 0, |
| | | working_voltage: str, |
| | | working_current: str, |
| | | backup_battery_voltage: 0, |
| | | mode_code: -1, |
| | | cover_state: -1, |
| | | supplement_light_state: -1, |
| | | putter_state: -1, |
| | | |
| | | } as DockOsd, |
| | | device: { |
| | |
| | | |
| | | watch(() => store.state.deviceStatusEvent, |
| | | data => { |
| | | if (root.$map === undefined) { |
| | | return |
| | | } |
| | | deviceTsaUpdateHook.value = deviceTsaUpdate() |
| | | if (Object.keys(data.deviceOnline).length !== 0) { |
| | | deviceTsaUpdateHook.value.initMarker(data.deviceOnline.domain, data.deviceOnline.device_callsign, data.deviceOnline.sn) |
| | |
| | | ) |
| | | |
| | | watch(() => store.state.deviceState, data => { |
| | | if (root.$aMap === undefined) { |
| | | return |
| | | } |
| | | if (!deviceTsaUpdateHook.value) { |
| | | deviceTsaUpdateHook.value = deviceTsaUpdate() |
| | | } |
| | |
| | | } |
| | | } |
| | | if (data.currentType === EDeviceTypeName.Dock && data.dockInfo[data.currentSn]) { |
| | | deviceTsaUpdateHook.value.initMarker(EDeviceTypeName.Dock, EDeviceTypeName.Dock, data.currentSn, data.dockInfo[data.currentSn].longitude, data.dockInfo[data.currentSn].latitude) |
| | | deviceTsaUpdateHook.value.initMarker(EDeviceTypeName.Dock, [EDeviceTypeName.Dock], data.currentSn, data.dockInfo[data.currentSn].basic_osd?.longitude, data.dockInfo[data.currentSn].basic_osd?.latitude) |
| | | if (osdVisible.value.visible && osdVisible.value.is_dock && osdVisible.value.gateway_sn !== '') { |
| | | deviceInfo.dock = data.dockInfo[osdVisible.value.gateway_sn] |
| | | deviceInfo.device = data.deviceInfo[deviceInfo.dock.sub_device?.device_sn] |
| | | deviceInfo.device = data.deviceInfo[deviceInfo.dock.basic_osd.sub_device?.device_sn ?? osdVisible.value.sn] |
| | | } |
| | | } |
| | | }, { |
| | |
| | | controlPanelVisible, |
| | | dockDebugOnOff, |
| | | setControlPanelVisible, |
| | | NetworkStateTypeEnum, |
| | | NetworkStateQualityEnum, |
| | | RainfallEnum, |
| | | DroneInDockEnum |
| | | } |
| | | } |
| | | }) |
| | |
| | | opacity: 0.7; |
| | | } |
| | | .osd > div { |
| | | padding-top: 5px; |
| | | margin-top: 5px; |
| | | padding-left: 5px; |
| | | } |
| | | |
| | |
| | | language: 'en', |
| | | begin_time: new Date(new Date().setDate(new Date().getDate() - 7)).setHours(0, 0, 0, 0), |
| | | end_time: new Date().setHours(23, 59, 59, 999), |
| | | domain: '', |
| | | domain: -1, |
| | | level: '', |
| | | message: '' |
| | | }) |
| | |
| | | const deviceTypes = [ |
| | | { |
| | | label: 'All', |
| | | value: '' |
| | | value: -1 |
| | | }, { |
| | | label: EDeviceTypeName.Aircraft, |
| | | label: EDeviceTypeName[EDeviceTypeName.Aircraft], |
| | | value: EDeviceTypeName.Aircraft |
| | | }, { |
| | | label: EDeviceTypeName.Dock, |
| | | label: EDeviceTypeName[EDeviceTypeName.Dock], |
| | | value: EDeviceTypeName.Dock |
| | | } |
| | | ] |
| | |
| | | getHms() |
| | | } |
| | | |
| | | function onDeviceTypeSelect (val: string) { |
| | | function onDeviceTypeSelect (val: number) { |
| | | param.sns = [param.device_sn, param.children_sn] |
| | | if (val === EDeviceTypeName.Dock) { |
| | | param.sns = [param.device_sn, ''] |
| | |
| | | CloseOutlined |
| | | } from '@ant-design/icons-vue' |
| | | import { useDockControl } from './useDockControl' |
| | | import { DeviceInfoType } from '/@/types/device' |
| | | import { DeviceInfoType, EDockModeCode } from '/@/types/device' |
| | | import { cmdList as baseCmdList, DeviceCmdItem } from '/@/types/device-cmd' |
| | | import { useMyStore } from '/@/store' |
| | | import { updateDeviceCmdInfoByOsd, updateDeviceCmdInfoByExecuteInfo } from '/@/utils/device-cmd' |
| | |
| | | } |
| | | |
| | | // dock 控制指令 |
| | | const debugStatus = ref(false) |
| | | const debugStatus = ref(props.deviceInfo.dock?.basic_osd.mode_code === EDockModeCode.Remote_Debugging) |
| | | |
| | | async function onDeviceStatusChange (status: boolean) { |
| | | let result = false |
| | |
| | | </div> |
| | | <div class="ml10 mt5" style="color: hsla(0,0%,100%,0.65);"> |
| | | <span><RocketOutlined /></span> |
| | | <span class="ml5">{{ dock.children?.nickname }}</span> |
| | | <span class="ml5">{{ dock.children?.nickname ?? 'No drone' }}</span> |
| | | </div> |
| | | </div> |
| | | </a-form-item> |
| | |
| | | :pagination="paginationProp" :scroll="{ x: '100%', y: 600 }" @change="refreshData"> |
| | | <!-- 执行时间 --> |
| | | <template #duration="{ record }"> |
| | | <div> |
| | | <div>{{ formatTaskTime(record.execute_time) }}</div> |
| | | <div>{{ formatTaskTime(record.end_time) }}</div> |
| | | <div class="flex-row"> |
| | | <div> |
| | | <div>{{ formatTaskTime(record.begin_time) }}</div> |
| | | <div>{{ formatTaskTime(record.end_time) }}</div> |
| | | </div> |
| | | <div class="ml10"> |
| | | <div>{{ formatTaskTime(record.execute_time) }}</div> |
| | | <div>{{ formatTaskTime(record.completed_time) }}</div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | <!-- 状态 --> |
| | |
| | | { |
| | | title: 'Planned/Actual Time', |
| | | dataIndex: 'duration', |
| | | width: 160, |
| | | width: 200, |
| | | slots: { customRender: 'duration' }, |
| | | }, |
| | | { |
| | |
| | | import dockIcon from '/@/assets/icons/dock.png' |
| | | import rcIcon from '/@/assets/icons/rc.png' |
| | | import droneIcon from '/@/assets/icons/drone.png' |
| | | import { EDeviceTypeName } from '/@/types' |
| | | |
| | | export function deviceTsaUpdate () { |
| | | const root = getRoot() |
| | | const AMap = root.$aMap |
| | | |
| | | const icons = new Map([ |
| | | ['sub-device', droneIcon], |
| | | ['gateway', rcIcon], |
| | | ['dock', dockIcon] |
| | | [EDeviceTypeName.Aircraft, droneIcon], |
| | | [EDeviceTypeName.Gateway, rcIcon], |
| | | [EDeviceTypeName.Dock, dockIcon] |
| | | ]) |
| | | const markers = store.state.markerInfo.coverMap |
| | | const paths = store.state.markerInfo.pathMap |
| | | |
| | | // Fix: 航迹初始化报错 |
| | | // TODO: 从时序上解决 |
| | | let trackLine = null as any |
| | | function getTrackLineInstance () { |
| | | if (!trackLine) { |
| | |
| | | return trackLine |
| | | } |
| | | |
| | | function initIcon (type: string) { |
| | | function initIcon (type: number) { |
| | | return new AMap.Icon({ |
| | | image: icons.get(type), |
| | | imageSize: new AMap.Size(40, 40), |
| | |
| | | }) |
| | | } |
| | | |
| | | function initMarker (type: string, name: string, sn: string, lng?: number, lat?: number) { |
| | | if (AMap === undefined) { |
| | | location.reload() |
| | | return |
| | | } |
| | | function initMarker (type: number, name: string, sn: string, lng?: number, lat?: number) { |
| | | if (markers[sn]) { |
| | | return |
| | | } |
| | |
| | | const components = apiPilot.init() |
| | | const exitVisible = ref(false) |
| | | const drawerVisible = ref(false) |
| | | let minitor = -1 |
| | | let minitor: any |
| | | |
| | | interface DeviceInfoData { |
| | | data: DeviceStatus |
| | |
| | | bound_status: false, |
| | | model: '', |
| | | gateway_sn: EStatusValue.DISCONNECT, |
| | | domain: '' |
| | | domain: -1 |
| | | } |
| | | }) |
| | | const bindParam: BindBody = { |
| | |
| | | // 监听ws 消息 |
| | | useConnectWebSocket(messageHandler) |
| | | |
| | | let bindNum: number |
| | | let bindNum: any |
| | | |
| | | onMounted(() => { |
| | | apiPilot.onBackClickReg() |
| | | apiPilot.onStopPlatform() |
| | | |
| | | window.connectCallback = arg => { |
| | | window.connectCallback = (arg: any) => { |
| | | connectCallback(arg) |
| | | } |
| | | window.wsConnectCallback = arg => { |
| | | window.wsConnectCallback = (arg: any) => { |
| | | wsConnectCallback(arg) |
| | | } |
| | | device.data.gateway_sn = apiPilot.getRemoteControllerSN() |
| | |
| | | apiPilot.loadComponent(EComponentName.Mission, {}) |
| | | |
| | | bindNum = setInterval(() => { |
| | | if (!bindParam.device_sn) { |
| | | device.data.gateway_sn = apiPilot.getRemoteControllerSN() |
| | | bindParam.device_sn = device.data.gateway_sn |
| | | return |
| | | } |
| | | bindDevice(bindParam).then(bindRes => { |
| | | if (bindRes.code !== 0) { |
| | | message.error(bindRes.message) |
| | |
| | | </a-form-item> |
| | | <a-form-item name="device_name" label="Device Name" required> |
| | | <a-select |
| | | style="width: 150px" |
| | | style="width: 220px" |
| | | mode="multiple" |
| | | placeholder="can choose multiple" |
| | | v-model:value="uploadParam.device_name"> |
| | | <a-select-option |
| | | v-for="item in deviceNameList" |
| | | :key="item.label" |
| | | :value="item.value" |
| | | v-for="k in DeviceNameEnum" |
| | | :key="k" |
| | | :value="k" |
| | | > |
| | | {{ item.label }} |
| | | {{ k }} |
| | | </a-select-option> |
| | | </a-select> |
| | | </a-form-item> |
| | |
| | | <div class="table flex-display flex-column"> |
| | | <a-table :columns="columns" :data-source="data.firmware" :pagination="paginationProp" @change="refreshData" row-key="firmware_id" |
| | | :rowClassName="(record, index) => ((index % 2) === 0 ? 'table-striped' : null)" :scroll="{ x: '100%', y: 600 }"> |
| | | <template v-for="col in ['mqtt_username', 'mqtt_password']" #[col]="{ text, record }" :key="col"> |
| | | <div> |
| | | <a-input |
| | | v-if="editableData[record.user_id]" |
| | | v-model:value="editableData[record.user_id][col]" |
| | | style="margin: -5px 0" |
| | | /> |
| | | <template v-else> |
| | | {{ text }} |
| | | </template> |
| | | <template #device_name="{ record }"> |
| | | <div v-for="text in record.device_name" :key="text"> |
| | | {{ text }} |
| | | </div> |
| | | </template> |
| | | <template #file_size="{ record }"> |
| | |
| | | firmware: Firmware[] |
| | | } |
| | | const columns = [ |
| | | { title: 'Model', dataIndex: 'device_name', width: 120, className: 'titleStyle' }, |
| | | { title: 'Model', dataIndex: 'device_name', width: 120, ellipsis: true, className: 'titleStyle', slots: { customRender: 'device_name' } }, |
| | | { title: 'File Name', dataIndex: 'file_name', width: 220, ellipsis: true, className: 'titleStyle', slots: { customRender: 'file_name' } }, |
| | | { title: 'Firmware Version', dataIndex: 'product_version', width: 180, className: 'titleStyle' }, |
| | | { title: 'File Size', dataIndex: 'file_size', width: 150, className: 'titleStyle', slots: { customRender: 'file_size' } }, |
| | |
| | | |
| | | const sVisible = ref(false) |
| | | const uploadParam = reactive<FirmwareUploadParam>({ |
| | | device_name: '', |
| | | device_name: [], |
| | | release_note: '', |
| | | status: true |
| | | }) |
| | |
| | | const rules = { |
| | | status: [{ required: true }], |
| | | release_note: [{ required: true, message: 'Please input release note.' }], |
| | | device_name: [{ required: true, message: 'Please select which model this firmware belongs to. Can not be [All].' }] |
| | | device_name: [{ required: true, message: 'Please select which models this firmware belongs to.' }] |
| | | } |
| | | interface FileItem { |
| | | uid: string; |
| | |
| | | const fileData = new FormData() |
| | | fileData.append('file', file as any, file.name) |
| | | Object.keys(uploadParam).forEach((key) => { |
| | | fileData.append(key, uploadParam[key as keyof FirmwareUploadParam].toString()) |
| | | const val = uploadParam[key as keyof FirmwareUploadParam] |
| | | if (val instanceof Array) { |
| | | val.forEach((value) => { |
| | | fileData.append(key, value) |
| | | }) |
| | | } else { |
| | | fileData.append(key, val.toString()) |
| | | } |
| | | }) |
| | | notification.open({ |
| | | key: uploading, |
| | |
| | | useDeviceUpgradeEvent(onDeviceUpgradeWs) |
| | | |
| | | // 获取设备列表信息 |
| | | function getDevices (domain: string, closeLoading?: boolean) { |
| | | function getDevices (domain: number, closeLoading?: boolean) { |
| | | if (!closeLoading) { |
| | | loading.value = true |
| | | } |
| | |
| | | <template> |
| | | <div> |
| | | <div class="height-100"> |
| | | <div style="height: 50px; line-height: 50px; border-bottom: 1px solid #4f4f4f; font-weight: 450;"> |
| | | <a-row> |
| | | <a-col :span="1"></a-col> |
| | |
| | | <a-col :span="1"></a-col> |
| | | </a-row> |
| | | </div> |
| | | <div v-if="docksData.data.length !== 0"> |
| | | <div v-for="dock in docksData.data" :key="dock.device_sn"> |
| | | <div v-if="dock?.children" class="panel" style="padding-top: 5px;" @click="selectDock(dock)"> |
| | | <div class="title"> |
| | | <a-tooltip :title="dock.nickname"> |
| | | <div class="pr10" style="width: 120px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;">{{ dock.nickname }}</div> |
| | | </a-tooltip> |
| | | </div> |
| | | <div class="ml10 mt5" style="color: hsla(0,0%,100%,0.65);"> |
| | | <span><RocketOutlined /></span> |
| | | <span class="ml5">{{ dock.children?.nickname }}</span> |
| | | <div class="scrollbar height-100" :style="{ height: scorllHeight + 'px'}"> |
| | | <div id="data" class=" uranus-scrollbar" v-if="docksData.data.length !== 0" @scroll="onScroll"> |
| | | <div v-for="dock in docksData.data" :key="dock.device_sn"> |
| | | <div class="panel" style="padding-top: 5px;" @click="selectDock(dock)"> |
| | | <div class="title"> |
| | | <a-tooltip :title="dock.nickname"> |
| | | <div class="pr10" style="width: 120px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;">{{ dock.nickname }}</div> |
| | | </a-tooltip> |
| | | </div> |
| | | <div class="ml10 mt5" style="color: hsla(0,0%,100%,0.65);"> |
| | | <span><RocketOutlined /></span> |
| | | <span class="ml5">{{ dock.children?.nickname ?? 'No drone' }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div v-else> |
| | | <a-empty :image-style="{ height: '60px', marginTop: '60px' }" /> |
| | | <div v-else> |
| | | <a-empty :image-style="{ height: '60px', marginTop: '60px' }" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | }) |
| | | |
| | | const workspaceId = localStorage.getItem(ELocalStorageKey.WorkspaceId)! |
| | | const scorllHeight = ref() |
| | | const canRefresh = ref(true) |
| | | |
| | | onMounted(() => { |
| | | const parent = document.getElementsByClassName('scrollbar').item(0)?.parentNode as HTMLDivElement |
| | | scorllHeight.value = document.body.clientHeight - parent.firstElementChild!.clientHeight |
| | | getDocks() |
| | | const key = setInterval(() => { |
| | | const data = document.getElementById('data')?.lastElementChild as HTMLDivElement |
| | | if (body.total === 0 || Math.ceil(body.total / body.page_size) <= body.page || scorllHeight.value <= data?.clientHeight + data?.offsetTop) { |
| | | clearInterval(key) |
| | | return |
| | | } |
| | | body.page++ |
| | | getDocks() |
| | | }, 1000) |
| | | }) |
| | | const body: IPage = { |
| | | page: 1, |
| | | total: 0, |
| | | page_size: 100 |
| | | total: -1, |
| | | page_size: 10, |
| | | } |
| | | function getDocks () { |
| | | getBindingDevices(workspaceId, body, EDeviceTypeName.Dock).then(res => { |
| | | |
| | | async function getDocks () { |
| | | if (!canRefresh.value) { |
| | | return |
| | | } |
| | | canRefresh.value = false |
| | | |
| | | await getBindingDevices(workspaceId, body, EDeviceTypeName.Dock).then(res => { |
| | | if (res.code !== 0) { |
| | | return |
| | | } |
| | | docksData.data = [] |
| | | res.data.list.forEach((dock: any) => { |
| | | if (dock.child_device_sn) { |
| | | docksData.data.push(dock) |
| | | } |
| | | }) |
| | | console.info(docksData.data) |
| | | docksData.data.push(...res.data.list) |
| | | body.page = res.data.pagination.page |
| | | body.page_size = res.data.pagination.page_size |
| | | body.total = res.data.pagination.total |
| | | }).finally(() => { |
| | | canRefresh.value = true |
| | | }) |
| | | } |
| | | |
| | | function onScroll (e: any) { |
| | | const element = e.srcElement |
| | | if (element.scrollTop + element.clientHeight >= element.scrollHeight - 5 && Math.ceil(body.total / body.page_size) > body.page && canRefresh.value) { |
| | | body.page++ |
| | | getDocks() |
| | | } |
| | | } |
| | | |
| | | function selectDock (dock: Device) { |
| | |
| | | margin: 0px 10px 0 10px; |
| | | } |
| | | } |
| | | .uranus-scrollbar { |
| | | overflow: auto; |
| | | scrollbar-width: thin; |
| | | scrollbar-color: #c5c8cc transparent; |
| | | height: 100%; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="project-layer-wrapper"> |
| | | <div class="project-layer-wrapper height-100"> |
| | | <div style="height: 50px; line-height: 50px; border-bottom: 1px solid #4f4f4f; font-weight: 450;"> |
| | | <a-row> |
| | | <a-col :span="1"></a-col> |
| | |
| | | <a-col :span="1"></a-col> |
| | | </a-row> |
| | | </div> |
| | | <div class="scrollbar" :style="{ height: scorllHeight + 'px'}"> |
| | | <LayersTree |
| | | :layer-data="mapLayers" |
| | | class="project-layer-content" |
| | |
| | | v-model:selectedKeys="selectedKeys" |
| | | v-model:checkedKeys="checkedKeys" |
| | | /> |
| | | </div> |
| | | <a-drawer |
| | | title="Map Element" |
| | | placement="right" |
| | |
| | | { id: 5, name: 'RED', color: '#E23C39', selected: false }, |
| | | { id: 6, name: 'NAME_DEFAULT', color: '#212121', selected: false } |
| | | ]) |
| | | const scorllHeight = ref() |
| | | |
| | | async function getAllElement () { |
| | | getElementGroups('init') |
| | |
| | | } |
| | | } |
| | | onMounted(() => { |
| | | const element = document.getElementsByClassName('scrollbar').item(0) as HTMLDivElement |
| | | const parent = element?.parentNode as HTMLDivElement |
| | | scorllHeight.value = parent.clientHeight - parent.firstElementChild!.clientHeight |
| | | getAllElement() |
| | | }) |
| | | function closeDrawer () { |
| | |
| | | margin-bottom: 10px; |
| | | } |
| | | } |
| | | .scrollbar { |
| | | overflow: auto; |
| | | } |
| | | </style> |
| | |
| | | <a-col :span="1"></a-col> |
| | | </a-row> |
| | | </div> |
| | | <div> |
| | | <div class="scrollbar" :style="{ height: scorllHeight + 'px'}"> |
| | | <a-collapse :bordered="false" expandIconPosition="right" accordion style="background: #232323;"> |
| | | <a-collapse-panel :key="EDeviceTypeName.Dock" header="Dock" style="border-bottom: 1px solid #4f4f4f;"> |
| | | <div v-if="onlineDocks.data.length === 0" style="height: 150px; color: white;"> |
| | |
| | | <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"> |
| | | <span class="text-hidden" style="max-width: 200px;">{{ dock.gateway.callsign }}</span> |
| | | <a-tooltip :title="`${dock.gateway.callsign} - ${dock.callsign ?? 'No Drone'}`"> |
| | | <span class="text-hidden" style="max-width: 200px;">{{ dock.gateway.callsign }} - {{ dock.callsign ?? 'No Drone' }}</span> |
| | | </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> |
| | | <span class="font-bold text-hidden" style="max-width: 80px;" :style="dockInfo[dock.gateway.sn] && dockInfo[dock.gateway.sn].mode_code !== EDockModeCode.Disconnected ? 'color: #00ee8b' : 'color: red;'"> |
| | | {{ dockInfo[dock.gateway.sn] ? EDockModeCode[dockInfo[dock.gateway.sn].mode_code] : EDockModeCode[EDockModeCode.Disconnected] }} |
| | | <span 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] }} |
| | | </span> |
| | | </div> |
| | | <div class="mr5 flex-align-center flex-row" style="width: 85px; margin-right: 0; height: 18px;"> |
| | |
| | | </div> |
| | | </div> |
| | | <div style="float: right; background: #595959; height: 100%; width: 40px;" class="flex-row flex-justify-center flex-align-center"> |
| | | <div class="fz16" @click="switchVisible($event, dock, true, dockInfo[dock.gateway.sn] && dockInfo[dock.gateway.sn].mode_code !== EDockModeCode.Disconnected)"> |
| | | <div class="fz16" @click="switchVisible($event, dock, true, dockInfo[dock.gateway.sn] && dockInfo[dock.gateway.sn].basic_osd?.mode_code !== EDockModeCode.Disconnected)"> |
| | | <a v-if="osdVisible.gateway_sn === dock.gateway.sn && osdVisible.visible"><EyeOutlined /></a> |
| | | <a v-else><EyeInvisibleOutlined /></a> |
| | | </div> |
| | |
| | | <div style="float: left; padding: 5px 5px 8px 8px; width: 88%"> |
| | | <div style="width: 100%; height: 100%;"> |
| | | <a-tooltip> |
| | | <template #title>{{ device.model }} - {{ device.callsign }}</template> |
| | | <span class="text-hidden" style="max-width: 200px; display: block; height: 20px;">{{ device.model }} - {{ device.callsign }}</span> |
| | | <template #title>{{ device.model ? `${device.model} - ${device.callsign}` : 'No Drone'}}</template> |
| | | <span class="text-hidden" style="max-width: 200px; display: block; height: 20px;">{{ device.model ? `${device.model} - ${device.callsign}` : 'No Drone'}}</span> |
| | | </a-tooltip> |
| | | </div> |
| | | <div class="mt5" style="background: #595959;"> |
| | |
| | | <div style="height: 20px; background: #595959; width: 94%;" > |
| | | <span class="mr5"><a-image style="margin-left: 2px; margin-top: -2px; height: 20px; width: 20px;" :src="rc" /></span> |
| | | <a-tooltip> |
| | | <template #title>{{ device.gateway.callsign }} </template> |
| | | <span>{{ device.gateway.callsign }}</span> |
| | | <template #title>{{ device.gateway.model }} - {{ device.gateway.callsign }} </template> |
| | | <span class="text-hidden" style="max-width: 200px;">{{ device.gateway.model }} - {{ device.gateway.callsign }}</span> |
| | | </a-tooltip> |
| | | </div> |
| | | </div> |
| | |
| | | const workspaceId = ref(localStorage.getItem(ELocalStorageKey.WorkspaceId)!) |
| | | const osdVisible = ref({} as OSDVisible) |
| | | const hmsVisible = new Map<string, boolean>() |
| | | const scorllHeight = ref() |
| | | |
| | | interface OnlineDevice { |
| | | model: string, |
| | |
| | | ) |
| | | getOnlineDeviceHms() |
| | | }, 3000) |
| | | const element = document.getElementsByClassName('scrollbar').item(0) as HTMLDivElement |
| | | const parent = element?.parentNode as HTMLDivElement |
| | | scorllHeight.value = parent?.clientHeight - parent.firstElementChild!.clientHeight |
| | | }) |
| | | |
| | | function getOnlineTopo () { |
| | |
| | | } |
| | | onlineDevices.data = [] |
| | | onlineDocks.data = [] |
| | | res.data.forEach((val: any) => { |
| | | const gateway = val.gateways_list.pop() |
| | | res.data.forEach((gateway: any) => { |
| | | const child = gateway.children |
| | | const device: OnlineDevice = { |
| | | model: val.device_name, |
| | | callsign: val.nickname, |
| | | sn: val.device_sn, |
| | | model: child?.device_name, |
| | | callsign: child?.nickname, |
| | | sn: child?.device_sn, |
| | | mode: EModeCode.Disconnected, |
| | | gateway: { |
| | | model: gateway?.device_name, |
| | |
| | | }, |
| | | payload: [] |
| | | } |
| | | val.payloads_list.forEach((payload: any) => { |
| | | child?.payloads_list.forEach((payload: any) => { |
| | | device.payload.push({ |
| | | model: payload.payload_name |
| | | }) |
| | | }) |
| | | if (gateway && EDeviceTypeName.Dock === gateway.domain) { |
| | | if (EDeviceTypeName.Dock === gateway.domain) { |
| | | hmsVisible.set(device.sn, false) |
| | | hmsVisible.set(device.gateway.sn, false) |
| | | onlineDocks.data.push(device) |
| | | } |
| | | if (val.status && EDeviceTypeName.Gateway === gateway.domain) { |
| | | if (gateway.status && EDeviceTypeName.Gateway === gateway.domain) { |
| | | onlineDevices.data.push(device) |
| | | } |
| | | }) |
| | |
| | | align-items: center; |
| | | border-bottom: 1px solid #4f4f4f; |
| | | } |
| | | .project-tsa-wrapper { |
| | | height: 100%; |
| | | .scrollbar { |
| | | overflow: auto; |
| | | } |
| | | ::-webkit-scrollbar { |
| | | display: none; |
| | | } |
| | | } |
| | | .ant-collapse > .ant-collapse-item > .ant-collapse-header { |
| | | color: white; |
| | | border: 0; |
| | |
| | | <template> |
| | | <div class="project-wayline-wrapper height-100"> |
| | | <a-spin :spinning="loading" :delay="300" tip="downloading" size="large"> |
| | | <div style="height: 50px; line-height: 50px; border-bottom: 1px solid #4f4f4f; font-weight: 450;"> |
| | | <a-row> |
| | | <a-col :span="1"></a-col> |
| | |
| | | </a-col> |
| | | </a-row> |
| | | </div> |
| | | <div class="height-100"> |
| | | <a-spin :spinning="loading" :delay="300" tip="downloading" size="large"> |
| | | <div class="scrollbar uranus-scrollbar" v-if="waylinesData.data.length !== 0" @scroll="onScroll"> |
| | | <div :style="{ height : height + 'px'}" class="scrollbar"> |
| | | <div id="data" class="height-100 uranus-scrollbar" v-if="waylinesData.data.length !== 0" @scroll="onScroll"> |
| | | <div v-for="wayline in waylinesData.data" :key="wayline.id"> |
| | | <div class="wayline-panel" style="padding-top: 5px;" @click="selectRoute(wayline)"> |
| | | <div class="title"> |
| | |
| | | </div> |
| | | </template> |
| | | </a-modal> |
| | | </a-spin> |
| | | </div> |
| | | </a-spin> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | const store = useMyStore() |
| | | const pagination :IPage = { |
| | | page: 1, |
| | | total: 0, |
| | | total: -1, |
| | | page_size: 10 |
| | | } |
| | | |
| | |
| | | const deleteWaylineId = ref<string>('') |
| | | const canRefresh = ref(true) |
| | | const importVisible = ref<boolean>(root.$router.currentRoute.value.name === ERouterName.WAYLINE) |
| | | const height = ref() |
| | | |
| | | onMounted(() => { |
| | | const parent = document.getElementsByClassName('scrollbar').item(0)?.parentNode as HTMLDivElement |
| | | height.value = document.body.clientHeight - parent.firstElementChild!.clientHeight |
| | | getWaylines() |
| | | setTimeout(() => { |
| | | const element = document.getElementsByClassName('scrollbar').item(0) as HTMLDivElement |
| | | const parent = element?.parentNode as HTMLDivElement |
| | | console.info(element, parent) |
| | | // console.info(element.scrollHeight, parent.clientHeight) |
| | | }, 1000) |
| | | }) |
| | | |
| | | onUpdated(() => { |
| | | const element = document.getElementsByClassName('scrollbar').item(0) as HTMLDivElement |
| | | const parent = element?.parentNode as HTMLDivElement |
| | | setTimeout(() => { |
| | | console.info(element, parent) |
| | | if (element?.scrollHeight < parent?.clientHeight && pagination.total > waylinesData.data.length) { |
| | | if (canRefresh.value) { |
| | | pagination.page++ |
| | | getWaylines() |
| | | } |
| | | } else if (element && element.className.indexOf('height-100') === -1) { |
| | | element.className = element.className + ' height-100' |
| | | const key = setInterval(() => { |
| | | const data = document.getElementById('data')?.lastElementChild as HTMLDivElement |
| | | if (pagination.total === 0 || Math.ceil(pagination.total / pagination.page_size) <= pagination.page || height.value <= data?.clientHeight + data?.offsetTop) { |
| | | clearInterval(key) |
| | | return |
| | | } |
| | | }, 300) |
| | | pagination.page++ |
| | | getWaylines() |
| | | }, 1000) |
| | | }) |
| | | |
| | | function getWaylines () { |
| | |
| | | if (res.code !== 0) { |
| | | return |
| | | } |
| | | waylinesData.data = [] |
| | | res.data.list.forEach((wayline: WaylineFile) => waylinesData.data.push(wayline)) |
| | | waylinesData.data = [...waylinesData.data, ...res.data.list] |
| | | pagination.total = res.data.pagination.total |
| | | pagination.page = res.data.pagination.page |
| | | }).finally(() => { |
| | |
| | | } |
| | | deleteWaylineId.value = '' |
| | | deleteTip.value = false |
| | | pagination.total-- |
| | | pagination.total = 0 |
| | | pagination.page = 1 |
| | | waylinesData.data = [] |
| | | getWaylines() |
| | | }) |
| | | } |
| | |
| | | |
| | | function onScroll (e: any) { |
| | | const element = e.srcElement |
| | | console.info(element) |
| | | if (element.scrollTop + element.clientHeight === element.scrollHeight && Math.ceil(pagination.total / pagination.page_size) > pagination.page && canRefresh.value) { |
| | | if (element.scrollTop + element.clientHeight >= element.scrollHeight - 5 && Math.ceil(pagination.total / pagination.page_size) > pagination.page && canRefresh.value) { |
| | | pagination.page++ |
| | | getWaylines() |
| | | } |
| | |
| | | if (res.code === 0) { |
| | | message.success(`${file.name} file uploaded successfully`) |
| | | canRefresh.value = true |
| | | pagination.total = 0 |
| | | pagination.page = 1 |
| | | waylinesData.data = [] |
| | | getWaylines() |
| | | } |
| | | }).finally(() => { |
| | |
| | | [sn: string]: DockOsd |
| | | }, |
| | | currentSn: '', |
| | | currentType: '' |
| | | currentType: -1 |
| | | }, |
| | | osdVisible: { |
| | | sn: '', |
| | |
| | | return |
| | | } |
| | | if (!state.deviceState.dockInfo[info.sn]) { |
| | | state.deviceState.dockInfo[info.sn] = info.host |
| | | return |
| | | state.deviceState.dockInfo[info.sn] = { } as DockOsd |
| | | } |
| | | state.deviceState.currentSn = info.sn |
| | | state.deviceState.currentType = EDeviceTypeName.Dock |
| | | const dock = state.deviceState.dockInfo[info.sn] |
| | | if (info.host.sdr) { |
| | | dock.sdr = info.host.sdr |
| | | dock.media_file_detail = info.host.media_file_detail |
| | | dock.wireless_link = info.host.wireless_link |
| | | dock.link_osd = info.host |
| | | return |
| | | } |
| | | if (info.host.job_number) { |
| | | if (info.host.drone_battery_maintenance_info) { |
| | | dock.drone_battery_maintenance_info = info.host.drone_battery_maintenance_info |
| | | } |
| | | dock.work_osd = info.host |
| | | return |
| | | } |
| | | const sdr = dock.sdr |
| | | const mediaFileDetail = dock.media_file_detail |
| | | const wireless = dock.wireless_link |
| | | state.deviceState.dockInfo[info.sn] = info.host |
| | | state.deviceState.dockInfo[info.sn].sdr = sdr |
| | | state.deviceState.dockInfo[info.sn].media_file_detail = mediaFileDetail |
| | | state.deviceState.dockInfo[info.sn].wireless_link = wireless |
| | | dock.basic_osd = info.host |
| | | }, |
| | | SET_DRAW_VISIBLE_INFO (state, bool) { |
| | | state.drawVisible = bool |
| | |
| | | file_name: string |
| | | product_version: string |
| | | file_size: number |
| | | device_name: string |
| | | device_name: string[] |
| | | username: string |
| | | release_note: string |
| | | released_time: string |
| | |
| | | } |
| | | |
| | | export interface FirmwareUploadParam { |
| | | device_name: string |
| | | device_name: string[] |
| | | release_note: string |
| | | status: boolean |
| | | } |
| | | |
| | | export enum DeviceNameEnum { |
| | | DJI_DOCK = 'DJI Dock', |
| | | MATRICE_30 = 'Matrice 30' |
| | | } |
| | | MATRICE_30 = 'Matrice 30', |
| | | MATRICE_30T = 'Matrice 30T' |
| | | } |
| | |
| | | bound_time: string, |
| | | login_time: string, |
| | | children?: Device[], |
| | | domain: string, |
| | | domain: number, |
| | | type: number, |
| | | firmware_progress?: number, // 升级进度 |
| | | } |
| | | |
| | |
| | | bound_status: boolean, |
| | | model: string, |
| | | gateway_sn: string, |
| | | domain: string |
| | | domain: number |
| | | } |
| | | |
| | | export interface OSDVisible { |
| | |
| | | obstacle_avoidance?: ObstacleAvoidance;// 飞行器避障开关设置 |
| | | } |
| | | |
| | | export interface DockOsd { |
| | | export enum NetworkStateTypeEnum { |
| | | FOUR_G = 1, |
| | | ETHERNET = 2, |
| | | } |
| | | |
| | | export enum NetworkStateQualityEnum { |
| | | BAD = 0, |
| | | MEDIUM = 1, |
| | | GOOD = 2 |
| | | } |
| | | |
| | | export enum RainfallEnum { |
| | | NONE = 0, |
| | | LIGHT_RAIN = 1, |
| | | MODERATE_RAIN = 2, |
| | | HEAVY_RAIN = 3, |
| | | } |
| | | |
| | | export enum DroneInDockEnum { |
| | | INSIDE, OUTSIDE |
| | | } |
| | | |
| | | export interface DockBasicOsd { |
| | | network_state: { |
| | | type: NetworkStateTypeEnum, |
| | | quality: number, |
| | | rate: number, |
| | | }, |
| | | drone_charge_state: { |
| | | state: number, |
| | | capacity_percent: number, |
| | | }, |
| | | drone_in_dock: DroneInDockEnum, |
| | | rainfall: RainfallEnum, |
| | | wind_speed: number, |
| | | environment_temperature: number, |
| | | temperature: number, |
| | | humidity: number, |
| | | latitude: number, |
| | | longitude: number, |
| | | height: number, |
| | | alternate_land_point: { |
| | | latitude: number, |
| | | longitude: number, |
| | | height: number, |
| | | safe_land_height: number, |
| | | is_configured: number |
| | | } |
| | | first_power_on: number, |
| | | positionState: { |
| | | gps_number: number, |
| | | is_fixed: number, |
| | | rtk_number: number, |
| | | is_calibration: number, |
| | | quality: number, |
| | | }, |
| | | storage: { |
| | | total: number, |
| | | used: number, |
| | | }, |
| | | mode_code: number, |
| | | cover_state: number, |
| | | supplement_light_state: number, |
| | | emergency_stop_state: number, |
| | | air_conditioner: { |
| | | air_conditioner_state: number, |
| | | switch_time: number, |
| | | } |
| | | battery_store_mode?: BatteryStoreModeEnum; // 电池保养(存储)模式 |
| | | alarm_state?: AlarmModeEnum; // 机场声光报警状态 |
| | | putter_state: number, |
| | | sub_device: { |
| | | device_sn?: string, |
| | | device_model_key?: string, |
| | | device_online_status: number, |
| | | device_paired: number, |
| | | }, |
| | | } |
| | | |
| | | export interface DockLinkOsd { |
| | | flighttask_prepare_capacity: number, |
| | | flighttask_step_code: number, |
| | | media_file_detail: { |
| | | remain_upload: number |
| | | }, |
| | |
| | | down_quality: string, |
| | | frequency_band: number, |
| | | }, |
| | | network_state: { |
| | | type: number, |
| | | quality: number, |
| | | rate: number, |
| | | }, |
| | | drone_in_dock: number, |
| | | drone_charge_state: { |
| | | state: number, |
| | | capacity_percent: string, |
| | | }, |
| | | rainfall: string, |
| | | wind_speed: string, |
| | | environment_temperature: string, |
| | | environment_humidity: string |
| | | temperature: string, |
| | | humidity: string, |
| | | latitude: number, |
| | | longitude: number, |
| | | height: number, |
| | | job_number: number, |
| | | acc_time: number, |
| | | first_power_on: number, |
| | | positionState: { |
| | | gps_number: string, |
| | | is_fixed: number, |
| | | rtk_number: string, |
| | | is_calibration: number, |
| | | quality: number, |
| | | }, |
| | | storage: { |
| | | total: number, |
| | | used: number, |
| | | }, |
| | | electric_supply_voltage: number, |
| | | working_voltage: string, |
| | | working_current: string, |
| | | backup_battery_voltage: number, |
| | | mode_code: number, |
| | | cover_state: number, |
| | | supplement_light_state: number, |
| | | putter_state: number, |
| | | sub_device: { |
| | | device_sn: string, |
| | | device_model_key: string, |
| | | device_online_status: number, |
| | | device_paired: number, |
| | | }, |
| | | alarm_state?: AlarmModeEnum; // 机场声光报警状态 |
| | | battery_store_mode?: BatteryStoreModeEnum; // 电池保养(存储)模式 |
| | | drone_battery_maintenance_info?: { // 飞行器电池保养信息 |
| | | maintenance_state: DroneBatteryStateEnum, // 保养状态 |
| | | maintenance_time_left: number, // 电池保养剩余时间(小时) |
| | | } |
| | | wireless_link?:{ |
| | | dongle_number: number, // dongle 数量 |
| | | ['4g_link_state']: FourGLinkStateEnum, // 4g_link_state |
| | |
| | | link_workmode: LinkWorkModeEnum, // 图传链路模式 |
| | | sdr_quality: number, // sdr信号质量 0-5 |
| | | ['4g_quality']: number, // 4G信号质量 0-5 |
| | | ['4g_freq_band']: number, |
| | | ['4g_gnd_quality']: number, |
| | | ['4g_uav_quality']: number, |
| | | sdr_freq_band: number, |
| | | } |
| | | } |
| | | |
| | | export interface MaintainStatus { |
| | | state: number, |
| | | last_maintain_type: number, |
| | | last_maintain_time: number, |
| | | last_maintain_work_sorties: number, |
| | | } |
| | | |
| | | export interface DockWorkOsd { |
| | | job_number: number, |
| | | acc_time: number, |
| | | activation_time: number, |
| | | maintain_status: { |
| | | maintain_status_array: MaintainStatus[] |
| | | } |
| | | electric_supply_voltage: number, |
| | | working_voltage: string, |
| | | working_current: string, |
| | | backup_battery: { |
| | | voltage: number, |
| | | temperature: number, |
| | | switch: number, |
| | | } |
| | | drone_battery_maintenance_info?: { // 飞行器电池保养信息 |
| | | maintenance_state: DroneBatteryStateEnum, // 保养状态 |
| | | maintenance_time_left: number, // 电池保养剩余时间(小时) |
| | | } |
| | | } |
| | | |
| | | export interface DockOsd { |
| | | basic_osd: DockBasicOsd, |
| | | link_osd: DockLinkOsd, |
| | | work_osd: DockWorkOsd |
| | | } |
| | | |
| | | export enum EModeCode { |
| | |
| | | message_zh: string, |
| | | create_time: string, |
| | | update_time: string, |
| | | domain: string |
| | | domain: number |
| | | } |
| | | |
| | | // TODO: 设备拓扑管理优化 |
| | |
| | | } |
| | | |
| | | export enum EDeviceTypeName { |
| | | Aircraft = 'sub-device', |
| | | Gateway = 'gateway', |
| | | Dock = 'dock', |
| | | Aircraft = 0, |
| | | Gateway = 2, |
| | | Dock = 3, |
| | | } |
| | | |
| | | export enum EHmsLevel { |
| | |
| | | |
| | | // 舱盖开关 |
| | | function getCoverState (cmdItem: DeviceCmdItem, airportProperties: any) { |
| | | const coverState = airportProperties?.cover_state as CoverStateEnum |
| | | const coverState = airportProperties?.basic_osd?.cover_state as CoverStateEnum |
| | | |
| | | if (coverState === CoverStateEnum.Close || coverState === CoverStateEnum.Failed) { |
| | | cmdItem.status = DeviceCmdStatusText.DeviceCoverCloseNormalText |
| | |
| | | |
| | | // 推杆状态 |
| | | function getPutterState (cmdItem: DeviceCmdItem, airportProperties: any) { |
| | | const putterState = airportProperties?.putter_state as PutterStateEnum |
| | | const putterState = airportProperties?.basic_osd?.putter_state as PutterStateEnum |
| | | if (putterState === PutterStateEnum.Close || putterState === PutterStateEnum.Failed) { |
| | | cmdItem.status = DeviceCmdStatusText.DevicePutterCloseNormalText |
| | | cmdItem.operateText = DeviceCmdStatusText.DevicePutterCloseBtnText |
| | |
| | | |
| | | // 充电状态 |
| | | function getChargeState (cmdItem: DeviceCmdItem, airportProperties: any) { |
| | | const chargeState = airportProperties?.drone_charge_state |
| | | const chargeState = airportProperties?.basic_osd?.drone_charge_state |
| | | const state = chargeState?.state as ChargeStateEnum |
| | | if (!state) return |
| | | if (state === ChargeStateEnum.Charge) { |
| | |
| | | |
| | | // 机场存储格式化 |
| | | function deviceFormat (cmdItem: DeviceCmdItem, airportProperties: any) { |
| | | const airportStorage = airportProperties?.storage |
| | | const airportStorage = airportProperties?.basic_osd?.storage |
| | | const value = getAirportStorage(airportStorage) |
| | | cmdItem.status = value |
| | | } |
| | |
| | | |
| | | // 补光灯状态 |
| | | function getSupplementLightState (cmdItem: DeviceCmdItem, airportProperties: any) { |
| | | const supplementLightState = airportProperties?.supplement_light_state |
| | | const supplementLightState = airportProperties?.basic_osd?.supplement_light_state |
| | | if (supplementLightState === SupplementLightStateEnum.Close) { |
| | | cmdItem.operateText = DeviceCmdStatusText.DeviceSupplementLightCloseBtnText |
| | | cmdItem.status = DeviceCmdStatusText.DeviceSupplementLightCloseNormalText |
| | |
| | | |
| | | // 声光报警 |
| | | function getAlarmState (cmdItem: DeviceCmdItem, airportProperties: any) { |
| | | const alarmState = airportProperties?.alarm_state |
| | | const alarmState = airportProperties?.basic_osd?.alarm_state |
| | | if (alarmState === AlarmModeEnum.CLOSE) { |
| | | cmdItem.operateText = DeviceCmdStatusText.AlarmStateCloseBtnText |
| | | cmdItem.status = DeviceCmdStatusText.AlarmStateCloseNormalText |
| | |
| | | |
| | | // 机场电池模式 |
| | | function getBatteryStoreMode (cmdItem: DeviceCmdItem, airportProperties: any) { |
| | | const batteryStoreMode = airportProperties?.battery_store_mode |
| | | const batteryStoreMode = airportProperties?.basic_osd?.battery_store_mode |
| | | if (batteryStoreMode === BatteryStoreModeEnum.BATTERY_PLAN_STORE) { |
| | | cmdItem.operateText = DeviceCmdStatusText.BatteryStoreModePlanBtnText |
| | | cmdItem.status = DeviceCmdStatusText.BatteryStoreModePlanNormalText |
| | |
| | | |
| | | // 飞行器电池保养 |
| | | function getDroneBatteryMode (cmdItem: DeviceCmdItem, airportProperties: any) { |
| | | const maintenanceState = airportProperties?.drone_battery_maintenance_info?.maintenance_state |
| | | const maintenanceState = airportProperties?.work_osd?.drone_battery_maintenance_info?.maintenance_state |
| | | if (maintenanceState === DroneBatteryStateEnum.MaintenanceInProgress) { |
| | | cmdItem.operateText = DeviceCmdStatusText.DroneBatteryModeCloseBtnText |
| | | cmdItem.status = DeviceCmdStatusText.DroneBatteryModeMaintenanceInProgressText |
| | |
| | | |
| | | // 增强图传开关 |
| | | function getSdrWorkNode (cmdItem: DeviceCmdItem, airportProperties: any) { |
| | | const linkWorkMode = airportProperties?.wireless_link?.link_workmode |
| | | const linkWorkMode = airportProperties?.link_osd?.wireless_link?.link_workmode |
| | | if (linkWorkMode === LinkWorkModeEnum.SDR) { |
| | | cmdItem.operateText = DeviceCmdStatusText.SdrWorkModeFourCloseBtnText |
| | | cmdItem.status = DeviceCmdStatusText.SdrWorkModeFourGCloseNormalText |